##############################################################################
#                                                                            #
#    Rgedit: gedit plugin for R                                              #
#    Copyright (C) 2009-2010  Dan Dediu                                      #
#                                                                            #
#    This program is free software: you can redistribute it and/or modify    #
#    it under the terms of the GNU General Public License as published by    #
#    the Free Software Foundation, either version 3 of the License, or       #
#    (at your option) any later version.                                     #
#                                                                            #
#    This program is distributed in the hope that it will be useful,         #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of          #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           #
#    GNU General Public License for more details.                            #
#                                                                            #
#    You should have received a copy of the GNU General Public License       #
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.   #
#                                                                            #
##############################################################################


##############################################################################
#    This was inspired by rkward (http://sourceforge.net/projects/rkward/)   #
#    and Tinn-R (http://sourceforge.net/projects/tinn-r/) and aims to offer  #
#    a light-weight, GTK+ IDE for R in the spirit of the above applications. #
#                                                                            #
#    It uses a heavily modified version of Paolo Borelli's VTE terminal for  #
#    gedit to allow embedding of R consoles.                                 #
#    Inspiration and code from Sukimashita's Open URI Context Menu Plugin    #
#                                                                            #
#    The most important idea is that Rgedit does not need any custom R       #
#    package as the whole interaction processeds through the R console. This #
#    allows it to be ver light on resources and fast but also imposes a      #
#    number of restrictions on the "intimacy" of the interaction with R.     #
#                                                                            #
#    Nevertheless, Rgedit offers a range of tools very useful to the heavy   #
#    (and professional) R user, including syntax highlighting and advanced   #
#    editing (thanks gedit!), execution of the current line, selection,      #
#    the whole file or usr-defined persistent blocks of code as well as      #
#    several separate R consoles. For more details, see the help file.       #
#                                                                            #
##############################################################################


from gettext import gettext as _
import gtk
import gtk.glade
import gedit
import vte
import pickle
import pango
import gobject
import os
import signal
import webbrowser
import platform
import time
import urllib2
import glob
import sys
import time
import datetime
import re
import os.path
from xml.dom import minidom
import xml.sax.saxutils

# Menu item example, insert a new item in the Tools menu
ui_str = """<ui>
  <menubar name="MenuBar">
    <menu name="R" action="R">
        <menuitem name="RCtrlLine" action="RCtrlLine"/>
        <menuitem name="RCtrlSel" action="RCtrlSel"/>
        <menuitem name="RCtrlAll" action="RCtrlAll"/>
        <separator/>
        <menuitem name="RCtrlBlock1Run" action="RCtrlBlock1Run"/>
        <menuitem name="RCtrlBlock1Def" action="RCtrlBlock1Def"/>
        <separator/>
        <menuitem name="RCtrlBlock2Run" action="RCtrlBlock2Run"/>
        <menuitem name="RCtrlBlock2Def" action="RCtrlBlock2Def"/>
        <separator/>
        <menuitem name="RCtrlNewTab" action="RCtrlNewTab"/>
        <menuitem name="RCtrlClose" action="RCtrlClose"/>
        <menuitem name="RCtrlAttach" action="RCtrlAttach"/>
        <!--menuitem name="RCtrlNewTab" action="RCtrlNewTab"/-->
        <!--menuitem name="RCtrlLoadWorkspace" action="RCtrlLoadWorkspace"/-->
        <!--menuitem name="RCtrlSaveWorkspace" action="RCtrlSaveWorkspace"/-->
        <separator/>
        <menuitem name="RCtrlLandmark" action="RCtrlLandmark"/>
        <menuitem name="RCtrlWizards" action="RCtrlWizards"/>
        <!--menuitem name="RCtrlHelpSel" action="RCtrlHelpSel"/-->
        <!--menuitem name="RCtrlShowSel" action="RCtrlShowSel"/-->
        <!--menuitem name="RCtrlEditSel" action="RCtrlEditSel"/-->
        <separator/>
        <menuitem name="RCtrlShowHide" action="RCtrlShowHide"/>
        <menuitem name="RCtrlConfig" action="RCtrlConfig"/>
        <menuitem name="RCtrlUpdate" action="RCtrlUpdate"/>
        <menuitem name="RCtrlHelpRCtrl" action="RCtrlHelpRCtrl"/>
        <menuitem name="RCtrlAbout" action="RCtrlAbout"/>
    </menu>
  </menubar>
  <toolbar name="ToolBar">
    <separator/>
    <toolitem name="RCtrlLine" action="RCtrlLine"/>
    <toolitem name="RCtrlSel" action="RCtrlSel"/>
    <toolitem name="RCtrlAll" action="RCtrlAll"/>
    <toolitem name="RCtrlBlock1Run" action="RCtrlBlock1Run"/>
    <toolitem name="RCtrlBlock1Def" action="RCtrlBlock1Def"/>
    <toolitem name="RCtrlBlock2Run" action="RCtrlBlock2Run"/>
    <toolitem name="RCtrlBlock2Def" action="RCtrlBlock2Def"/>
    <toolitem name="RCtrlNewTab" action="RCtrlNewTab"/>
  </toolbar>
</ui>
"""

# The special comment used to put a landmark in the R code:
landmark_comment_header = "# @@ RGEDIT LANDMARK @@:"
landmark_comment_placeholder = " your text goes here"

########################################################
#                From GeditTerminal                    #
########################################################

try:
    gettext.bindtextdomain(GETTEXT_PACKAGE, GP_LOCALEDIR)
    _ = lambda s: gettext.dgettext(GETTEXT_PACKAGE, s);
except:
    _ = lambda s: s

class RGeditTerminal(gtk.HBox):

    __gsignals__ = {
        "populate-popup": (
            gobject.SIGNAL_RUN_LAST,
            None,
            (gobject.TYPE_OBJECT,)
        )
    }

    def __init__(self,plugin):
        gtk.HBox.__init__(self, False, 4)

        self._plugin = plugin

        self.vteTabs = gtk.Notebook()
        self.vteTabs.set_tab_pos(self._plugin.prefs['R_console_tab_pos'])
        self.vteTabs.set_show_tabs(self._plugin.prefs['R_console_always_show_tabs'])
        self.vteTabs.show()
        
        # A maximum of 3 tabs: keep track of tabs 2 and 3 (1 is always open):
        self._vte2 = None
        self._vte3 = None
        self._vte2_page_number = -1 # _vte2's page index (can be 1 or 2)
        self._vte3_page_number = -1 # _vte3's page index (can be 1 or 2)

        # And their names:
        self.tab_names = ["1","2","3"]

        # And the shell PIDs for each:
        self._vte1_shell_PID = -1;
        self._vte2_shell_PID = -1;
        self._vte3_shell_PID = -1;

        self._vteTab1 = gtk.HBox()
        self._vte = vte.Terminal()
        
        self.reconfigure_vte(self._vte,1)
        
        self._vte.set_size(self._vte.get_column_count(), 5)
        self._vte.set_size_request(200, 50)
        self._vte.show()
        self._vteTab1.pack_start(self._vte)
        self._vteTab1.show()
        self.vteTabs.append_page(self._vteTab1,gtk.Label(self.get_tab_name(1))) 
        self.pack_start(self.vteTabs)

        self._scrollbar = gtk.VScrollbar(self._vte.get_adjustment())
        self._scrollbar.show()
        self._vteTab1.pack_start(self._scrollbar, False, False, 0)

        self._vte.connect("key-press-event", self.on_vte_key_press)
        self._vte.connect("key-release-event", self.on_vte_key_release)
        self._vte.connect("button-press-event", self.on_vte_button_press)
        self._vte.connect("popup-menu", self.on_vte_popup_menu)
        self._vte.connect("child-exited", self.vte1_child_exited) #lambda term: term.fork_command())
        #self._vte.connect("commit", self.on_vte_committed)

        self._vte1_shell_PID = self._vte.fork_command()
        #print self._vte1_shell_PID
        
        # Is it a special Ctrl+C (used to implement the Ctrl+Q/ESC key in the R console):
        self.special_ctrl_c = False

    def run_gedit_helper_script(self,vte):
        # Run the gedit helper script
        #vte.feed_child("# Run misc stuff required by rgedit...\n")
        #vte.feed_child("source(\""+self._plugin.get_data_dir()+"/rgedit-helper-script.r\",echo=FALSE,print.eval=TRUE,max.deparse.length=500000,local=TRUE);\n")
        return
        
    def show_messages_and_warnings(self,vte):
        # Show a warning on the R console:
        if self._plugin.prefs['show_messages_and_warnings'] == False:
            return
        
        message_file = open(self._plugin.get_data_dir()+"/messages_and_warnings.txt","r")
        if not message_file:
            print "Error reading the messages and warnings file\n"
            return
            
        #vte.feed_child( "\n############################ rgedit messages #################################\n" )
        #for line in message_file:
            #vte.feed_child( "# " + line );
        #vte.feed_child( "################################################################################\n\n" )
        
    def vte1_child_exited(self,event):
        self._vte1_shell_PID = self._vte.fork_command()

    def on_vte_committed(self,vterm,text,textlen):
        #print text, textlen
        return true

    def do_grab_focus(self):
        self._vte.grab_focus()

    def reconfigure_vte(self,_vteN,tab_number):
        # Fonts
        font_name = self._plugin.prefs['font_name']
        try:
            _vteN.set_font(pango.FontDescription(font_name))
        except:
            pass

        # colors
        _vteN.ensure_style()
        style = _vteN.get_style()

        if self._plugin.prefs['foreground'+str(tab_number)] == None:
            fg = style.text[gtk.STATE_NORMAL]
        else:
            fg = gtk.gdk.color_parse(self._plugin.prefs['foreground'+str(tab_number)])

        if self._plugin.prefs['background'+str(tab_number)] == None:
            bg = style.base[gtk.STATE_NORMAL]
        else:
            bg = gtk.gdk.color_parse(self._plugin.prefs['background'+str(tab_number)])

        palette = []
        _vteN.set_colors(fg, bg, palette)

        # cursor blink
        try:
            if self._plugin.prefs['cursor_blink'] == "system":
                blink = vte.CURSOR_BLINK_SYSTEM
            elif self._plugin.prefs['cursor_blink'] == "on":
                blink = vte.CURSOR_BLINK_ON
            elif self._plugin.prefs['cursor_blink'] == "off":
                blink = vte.CURSOR_BLINK_OFF
            else:
                blink = vte.CURSOR_BLINK_SYSTEM
            _vteN.set_cursor_blink_mode(blink)
        except:
            pass

        # cursor shape
        try:
            if self._plugin.prefs['cursor_shape'] == "block":
                shape = vte.CURSOR_SHAPE_BLOCK
            elif self._plugin.prefs['cursor_shape'] == "ibeam":
                shape = vte.CURSOR_SHAPE_IBEAM
            elif self._plugin.prefs['cursor_shape'] == "underline":
                shape = vte.CURSOR_SHAPE_UNDERLINE
            else:
                shape = vte.CURSOR_SHAPE_BLOCK
            _vteN.set_cursor_shape(shape)
        except:
            pass

        _vteN.set_audible_bell(not self._plugin.prefs['audible_bell'])

        _vteN.set_scrollback_lines(self._plugin.prefs['scrollback_lines'])

        _vteN.set_allow_bold(self._plugin.prefs['allow_bold'])

        _vteN.set_scroll_on_keystroke(self._plugin.prefs['scroll_on_keystroke'])

        _vteN.set_scroll_on_output(self._plugin.prefs['scroll_on_output'])

        _vteN.set_word_chars(self._plugin.prefs['word_chars'])

        _vteN.set_emulation(self._plugin.prefs['emulation'])
        _vteN.set_visible_bell(self._plugin.prefs['visible_bell'])

    def on_vte_key_press(self, term, event):
        modifiers = event.state & gtk.accelerator_get_default_mod_mask()
        key_name = gtk.gdk.keyval_name(event.keyval)
        if key_name in ("v", "V") and modifiers == gtk.gdk.CONTROL_MASK:
            # Ctrl+V detected:
            self.paste_clipboard()
            return True
        if key_name in ("c", "C") and modifiers == gtk.gdk.CONTROL_MASK and not self.special_ctrl_c and self._plugin.prefs['R_console_Ctrl_C_4_copy']:
            # Ctrl+C detected:
            self.copy_clipboard()
            return True
        if (key_name in ("q", "Q") and modifiers == gtk.gdk.CONTROL_MASK and self._plugin.prefs['R_console_Ctrl_Q_break']) or (key_name == "Escape" and self._plugin.prefs['R_console_Escape_break']):
            # Ctrl+Q or ESC detected: simulate a Ctrl+C instead:
            self.break_R_computation()
            return True
        elif key_name == "Tab" and modifiers == gtk.gdk.CONTROL_MASK:
            # Ctrl+Tab detected:
            current_view = self._window.get_active_view()
            if current_view != None:
                current_view.grab_focus()
            return True
        elif key_name in ("k", "K") and modifiers == gtk.gdk.CONTROL_MASK:
            # Copy the current line to the clipboard:
            self.copy_last_line_to_clipboard()
            return True
        elif key_name in ("k", "K") and modifiers == (gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK):
            # Copy the current line to the clipboard and paste it into gedit:
            self.copy_last_line_to_clipboard()
            return True
        return False
        
    def on_vte_key_release(self, term, event):
        modifiers = event.state & gtk.accelerator_get_default_mod_mask()
        key_name = gtk.gdk.keyval_name(event.keyval)
        if key_name in ("k", "K") and modifiers == (gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK):
            # Paste the previously copied line into gedit:
            self.paste_last_line_from_clipboard_to_gedit()
            return True
        return False
        
    def break_R_computation(self):
        # Send a "hidden" Ctrl+C to the R process:
        vte = None
        if self.vteTabs.get_current_page() == 0:
            vte= self._vte
        elif self.vteTabs.get_current_page() == self._vte2_page_number:
            vte= self._vte2
        elif self.vteTabs.get_current_page() == self._vte3_page_number:
            vte= self._vte3
        else:
            print( "Unknown R tab!" )
            
        event = gtk.gdk.Event(gtk.gdk.KEY_PRESS)
        event.window = vte.window
        event.send_event = True
        event.state = gtk.gdk.CONTROL_MASK
        event.keyval = int(gtk.gdk.keyval_from_name('c'))
        self.special_ctrl_c = True
        vte.emit("key-press-event", event)
        self.special_ctrl_c = False

    def on_vte_button_press(self, term, event):
        if event.button == 3:
            self._vte.grab_focus()
            self.do_popup(event)
            return True

    def on_vte_popup_menu(self, term):
        self.do_popup()

    def create_popup_menu(self):
        menu = gtk.Menu()

        item = gtk.ImageMenuItem(gtk.STOCK_COPY)
        item.connect("activate", lambda menu_item: self.copy_clipboard())
        if self.vteTabs.get_current_page() == 0:
            item.set_sensitive(self._vte.get_has_selection())
        elif self.vteTabs.get_current_page() == self._vte2_page_number:
            item.set_sensitive(self._vte2.get_has_selection())
        elif self.vteTabs.get_current_page() == self._vte3_page_number:
            item.set_sensitive(self._vte3.get_has_selection())
        else:
            print( "Unknown R tab!" )
        menu.append(item)

        item = gtk.ImageMenuItem(gtk.STOCK_PASTE)
        item.connect("activate", lambda menu_item: self.paste_clipboard())
        menu.append(item)

        item = gtk.SeparatorMenuItem()
        menu.append(item)

        item = gtk.MenuItem("Change tab name")
        item.connect("activate", lambda menu_item: self.change_tab_name())
        menu.append(item)

        item = gtk.CheckMenuItem("Always show tabs?")
        item.set_active(self._plugin.prefs['R_console_always_show_tabs'])
        item.connect("activate", lambda menu_item: self.always_show_tabs())
        menu.append(item)

        item = gtk.MenuItem("Show tabs on")
        menu.append(item)
        show_tabs_submenu = gtk.Menu()
        tabs_top = gtk.CheckMenuItem("top")
        tabs_top.set_draw_as_radio(True)
        tabs_top.set_active(self._plugin.prefs['R_console_tab_pos'] == gtk.POS_TOP)
        tabs_top.connect("activate", lambda menu_item: self.show_tabs_top())
        tabs_left = gtk.CheckMenuItem("left")
        tabs_left.set_draw_as_radio(True)
        tabs_left.set_active(self._plugin.prefs['R_console_tab_pos'] == gtk.POS_LEFT)
        tabs_left.connect("activate", lambda menu_item: self.show_tabs_left())
        tabs_right = gtk.CheckMenuItem("right")
        tabs_right.set_draw_as_radio(True)
        tabs_right.set_active(self._plugin.prefs['R_console_tab_pos'] == gtk.POS_RIGHT)
        tabs_right.connect("activate", lambda menu_item: self.show_tabs_right())
        tabs_bottom = gtk.CheckMenuItem("bottom")
        tabs_bottom.set_draw_as_radio(True)
        tabs_bottom.set_active(self._plugin.prefs['R_console_tab_pos'] == gtk.POS_BOTTOM)
        tabs_bottom.connect("activate", lambda menu_item: self.show_tabs_bottom())
        show_tabs_submenu.attach(tabs_top,0,1,0,1)
        show_tabs_submenu.attach(tabs_left,0,1,1,2)
        show_tabs_submenu.attach(tabs_right,0,1,2,3)
        show_tabs_submenu.attach(tabs_bottom,0,1,3,4)
        item.set_submenu(show_tabs_submenu)

        item = gtk.MenuItem("Close tab")
        item.connect("activate", lambda menu_item: self.close_tab())
        if self.vteTabs.get_current_page() == 0:
            item.set_sensitive(False)
        menu.append(item)

        item = gtk.MenuItem("Start R")
        item.connect("activate", lambda menu_item: self.start_R())
        menu.append(item)

        item = gtk.MenuItem("Restart R")
        item.connect("activate", lambda menu_item: self.restart_R())
        menu.append(item)
        
        item = gtk.SeparatorMenuItem()
        menu.append(item)

        item = gtk.MenuItem("Change R's working folder")
        item.connect("activate", lambda menu_item: self.change_R_working_dir())
        menu.append(item)

        item = gtk.MenuItem("Use document's folder")
        item.connect("activate", lambda menu_item: self.change_R_working_dir_to_the_document())
        menu.append(item)

        item = gtk.ImageMenuItem("Load R workspace")
        item_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self._plugin.get_data_dir()+"/load_workspace.png" , 24, 24)
        item_icon.set_from_pixbuf(pixbuf)
        item_icon.show()
        item.set_image(item_icon)
        item.connect("activate", lambda menu_item: self.on_R_load_workspace())
        menu.append(item)

        item = gtk.ImageMenuItem("Save R workspace")
        item_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self._plugin.get_data_dir()+"/save_workspace.png" , 24, 24)
        item_icon.set_from_pixbuf(pixbuf)
        item_icon.show()
        item.set_image(item_icon)
        item.connect("activate", lambda menu_item: self.on_R_save_workspace())
        menu.append(item)

        self.emit("populate-popup", menu)
        menu.show_all()
        return menu

    def do_popup(self, event = None):
        menu = self.create_popup_menu()

        if event is not None:
            menu.popup(None, None, None, event.button, event.time)
        else:
            menu.popup(None, None,
                       lambda m: gedit.utils.menu_position_under_widget(m, self),
                       0, gtk.get_current_event_time())
            menu.select_first(False)

    def copy_clipboard(self):
        if self.vteTabs.get_current_page() == 0:
            self._vte.copy_clipboard()
            self._vte.grab_focus()
        elif self.vteTabs.get_current_page() == self._vte2_page_number:
            self._vte2.copy_clipboard()
            self._vte2.grab_focus()
        elif self.vteTabs.get_current_page() == self._vte3_page_number:
            self._vte3.copy_clipboard()
            self._vte3.grab_focus()
        else:
            print( "Unknown R tab!" )

    def paste_clipboard(self):
        if self.vteTabs.get_current_page() == 0:
            self._vte.paste_clipboard()
            self._vte.grab_focus()
        elif self.vteTabs.get_current_page() == self._vte2_page_number:
            self._vte2.paste_clipboard()
            self._vte2.grab_focus()
        elif self.vteTabs.get_current_page() == self._vte3_page_number:
            self._vte3.paste_clipboard()
            self._vte3.grab_focus()
        else:
            print( "Unknown R tab!" )
            
    def copy_last_line_to_clipboard(self):
        # Copy the current line to the clipboard by invoking the .rgedit.lastline2clipboard function from the helper script:
        clipboard_command = '.rgedit.lastline2clipboard()\n'
        if self.vteTabs.get_current_page() == 0:
            self._vte.feed_child(clipboard_command)
            self._vte.grab_focus()
        elif self.vteTabs.get_current_page() == self._vte2_page_number:
            self._vte2.feed_child(clipboard_command)
            self._vte2.grab_focus()
        elif self.vteTabs.get_current_page() == self._vte3_page_number:
            self._vte3.feed_child(clipboard_command)
            self._vte3.grab_focus()
        else:
            print( "Unknown R tab!" )
            
    def paste_last_line_from_clipboard_to_gedit(self):
        # Paste the previously copied line into gedit:
        app  = gedit.app_get_default()
        win  = app.get_active_window()
        doc  = win.get_active_document()
        #doc = self._plugin.get_active_window().get_active_document()
        if not doc:
            return
        #doc.insert_at_cursor("KUK\n");
        doc.paste_clipboard(gtk.clipboard_get(selection="CLIPBOARD"),None,True)
        #fake_clipboard = gtk.Clipboard(gtk.gdk.display_get_default(),"_rgedit_fake_clipboard")
        #fake_clipboard.set_text("\n")
        #doc.paste_clipboard(fake_clipboard,None,True)
 
    def change_directory(self, path):
        path = path.replace('\\', '\\\\').replace('"', '\\"')
        self._vte.feed_child('cd "%s"\n' % path)
        self._vte.grab_focus()

    def send_command(self,string):
        if self.vteTabs.get_current_page() == 0:
            self._vte.feed_child(string)
        elif self.vteTabs.get_current_page() == self._vte2_page_number:
            self._vte2.feed_child(string)
        elif self.vteTabs.get_current_page() == self._vte3_page_number:
            self._vte3.feed_child(string)
        else:
            print( "Unknown R tab!" )
            print( self.vteTabs.get_current_page() )
            print( self._vte2_page_number )
            print( self._vte3_page_number )

    def create_new_R_tab(self):
        if self._vte2 == None:
           # _vte2 is free:
           self._vteTab2 = gtk.HBox()
           self._vte2 = vte.Terminal()
           self.reconfigure_vte(self._vte2,2)
           self._vte2.set_size(self._vte2.get_column_count(), 5)
           self._vte2.set_size_request(200, 50)
           self._vte2.show()
           self._vteTab2.pack_start(self._vte2)
           self._vteTab2.show()
           self.vteTabs.append_page(self._vteTab2,gtk.Label(self.get_tab_name(2))) 
           self.vteTabs.set_show_tabs(True)
           self._vte2_page_number = self.vteTabs.get_n_pages()-1

           self._scrollbar2 = gtk.VScrollbar(self._vte2.get_adjustment())
           self._scrollbar2.show()
           self._vteTab2.pack_start(self._scrollbar2, False, False, 0)

           self._vte2.connect("key-press-event", self.on_vte_key_press)
           self._vte2.connect("button-press-event", self.on_vte_button_press)
           self._vte2.connect("popup-menu", self.on_vte_popup_menu)
           self._vte2.connect("child-exited", self.on_vte2_exited)

           self._vte2_shell_PID = self._vte2.fork_command()

           self._vte2.feed_child("ghci \n") # open R
           self.run_gedit_helper_script(self._vte2)
           if self._plugin.prefs['use_current_document_directory']:
               self.change_vte_R_working_dir_to_the_document(self._vte2)
           self.show_messages_and_warnings(self._vte2)

           if self._vte3 != None:
               # All 3 tabs are active:
               manager = self._window.get_ui_manager()
               manager.get_action("/ToolBar/RCtrlNewTab").set_sensitive(False)


        elif self._vte3 == None:
           # _vte3 is free:
           self._vteTab3 = gtk.HBox()
           self._vte3 = vte.Terminal()
           self.reconfigure_vte(self._vte3,3)
           self._vte3.set_size(self._vte3.get_column_count(), 5)
           self._vte3.set_size_request(200, 50)
           self._vte3.show()
           self._vteTab3.pack_start(self._vte3)
           self._vteTab3.show()
           self.vteTabs.append_page(self._vteTab3,gtk.Label(self.get_tab_name(3))) 
           self.vteTabs.set_show_tabs(True)
           self._vte3_page_number = self.vteTabs.get_n_pages()-1

           self._scrollbar3 = gtk.VScrollbar(self._vte3.get_adjustment())
           self._scrollbar3.show()
           self._vteTab3.pack_start(self._scrollbar3, False, False, 0)

           self._vte3.connect("key-press-event", self.on_vte_key_press)
           self._vte3.connect("button-press-event", self.on_vte_button_press)
           self._vte3.connect("popup-menu", self.on_vte_popup_menu)
           self._vte3.connect("child-exited", self.on_vte3_exited)

           self._vte3_shell_PID = self._vte3.fork_command()

           self._vte3.feed_child("ghci \n") # open R
           self.run_gedit_helper_script(self._vte3)
           if self._plugin.prefs['use_current_document_directory']:
               self.change_vte_R_working_dir_to_the_document(self._vte3)
           self.show_messages_and_warnings(self._vte3)

           if self._vte2 != None:
               # All 3 tabs are active:
               manager = self._window.get_ui_manager()
               manager.get_action("/ToolBar/RCtrlNewTab").set_sensitive(False)

    def kill_shell_process(self,PID):
        # Kill the shell process with the given PID
        #return # Not really working...
        if PID > 0:
            print "Kill " + str(PID)
            os.kill(PID,signal.SIGHUP)

    def on_vte2_exited(self,event):
        # destroy the _vte2:
        self.vteTabs.remove_page(self.vteTabs.get_current_page())
        if self.vteTabs.get_n_pages() == 1:
            self.vteTabs.set_show_tabs(False)
        self._vte2 = None
        self._vte2_page_number = -1
        manager = self._window.get_ui_manager()
        manager.get_action("/ToolBar/RCtrlNewTab").set_sensitive(True)
        #self.kill_shell_process(self._vte2_shell_PID)
        #self._vte2_shell_PID = -1

    def on_vte3_exited(self,event):
        # destroy the _vte3:
        self.vteTabs.remove_page(self.vteTabs.get_current_page())
        if self.vteTabs.get_n_pages() == 1:
            self.vteTabs.set_show_tabs(False)
        self._vte3 = None
        self._vte3_page_number = -1
        manager = self._window.get_ui_manager()
        manager.get_action("/ToolBar/RCtrlNewTab").set_sensitive(True)
        #self.kill_shell_process(self._vte3_shell_PID)
        #self._vte3_shell_PID = -1

    def change_tab_name(self):
        tab_number = -1
        active_vte = None
        if self.vteTabs.get_current_page() == 0:
            tab_number = 1
        elif self.vteTabs.get_current_page() == self._vte2_page_number:
            tab_number = self._vte2_page_number+1
        elif self.vteTabs.get_current_page() == self._vte3_page_number:
            tab_number = self._vte3_page_number+1
        else:
            print( "Unknown R tab!" )

        ui = gtk.glade.XML(self._plugin.get_data_dir()+"/ChangeTabNameDialog.glade")

        # Init the controls accordingly with the current options:
        label_tab_number = ui.get_widget("TabNumber")
        label_tab_number.set_text(str(tab_number))

        edit_tab_name = ui.get_widget("TabName")
        edit_tab_name.set_text(self.tab_names[tab_number-1])

        dialog = ui.get_widget("ChangeTabNameDialog")

        #Create our dictionay and connect it
        response = dialog.run()
        if response == -2: #OK button
            self.tab_names[tab_number-1] = edit_tab_name.get_text()
            self.vteTabs.set_tab_label(self.vteTabs.get_nth_page(tab_number-1),gtk.Label(self.get_tab_name(tab_number)))
            vte1_console_changed = False
            vte2_console_changed = False
            vte3_console_changed = False
            vte1_R_options_changed = False
            vte2_R_options_changed = False
            vte3_R_options_changed = False
            if self._plugin.prefs['tab_name_in_prompt'] == True:
                vte1_R_options_changed = (tab_number == 1)
                vte2_R_options_changed = (tab_number == self._vte2_page_number+1)
                vte3_R_options_changed = (tab_number == self._vte3_page_number+1)
            self.reconfigure_vtes(vte1_console_changed,vte2_console_changed,vte3_console_changed,vte1_R_options_changed,vte2_R_options_changed,vte3_R_options_changed)
        dialog.destroy()


    def always_show_tabs(self):
        # Toggle the showing of R tabs:
        self._plugin.prefs['R_console_always_show_tabs'] = not self._plugin.prefs['R_console_always_show_tabs']
        self.vteTabs.set_show_tabs(self._plugin.prefs['R_console_always_show_tabs'])


    def show_tabs_right(self):
        # Toggle the showing of R tabs to the right:
        self._plugin.prefs['R_console_tab_pos'] = gtk.POS_RIGHT
        self.vteTabs.set_tab_pos(self._plugin.prefs['R_console_tab_pos'])


    def show_tabs_left(self):
        # Toggle the showing of R tabs to the left:
        self._plugin.prefs['R_console_tab_pos'] = gtk.POS_LEFT
        self.vteTabs.set_tab_pos(self._plugin.prefs['R_console_tab_pos'])


    def show_tabs_top(self):
        # Toggle the showing of R tabs to the top:
        self._plugin.prefs['R_console_tab_pos'] = gtk.POS_TOP
        self.vteTabs.set_tab_pos(self._plugin.prefs['R_console_tab_pos'])


    def show_tabs_bottom(self):
        # Toggle the showing of R tabs to the bottom:
        self._plugin.prefs['R_console_tab_pos'] = gtk.POS_BOTTOM
        self.vteTabs.set_tab_pos(self._plugin.prefs['R_console_tab_pos'])


    def reconfigure_vtes(self,vte1_console_changed,vte2_console_changed,vte3_console_changed,vte1_R_options_changed,vte2_R_options_changed,vte3_R_options_changed):
        if vte1_console_changed == True:
            self.reconfigure_vte(self._vte,1)
        #if vte1_R_options_changed == True:
            #if self._plugin.prefs['prompt_color1'] != None or self._plugin.prefs['tab_name_in_prompt'] == True:
               #self._vte.feed_child(self._plugin.prompt_string(1,self.get_tab_name(1))) # and set the prompt accordingly...

        if self._vte2 != None:
            if vte2_console_changed == True:
               self.reconfigure_vte(self._vte2,2)
            #if vte2_R_options_changed == True:
               #if self._plugin.prefs['prompt_color2'] != None or self._plugin.prefs['tab_name_in_prompt'] == True:
                   #self._vte2.feed_child(self._plugin.prompt_string(2,self.get_tab_name(2))) # and set the prompt accordingly...

        if self._vte3 != None:
            if vte3_console_changed == True:
               self.reconfigure_vte(self._vte3,3)
            #if vte3_R_options_changed == True:
               #if self._plugin.prefs['prompt_color3'] != None or self._plugin.prefs['tab_name_in_prompt'] == True:
                   #self._vte3.feed_child(self._plugin.prompt_string(3,self.get_tab_name(3))) # and set the prompt accordingly...

    def get_tab_name(self,tab_number):
        # Return the tab name:
        return self.tab_names[tab_number-1]

    def close_tab(self):
        if self.vteTabs.get_current_page() == self._vte2_page_number:
            question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "Are you sure you want to close this tab?" )
            response = question_dialog.run()
            question_dialog.destroy()

            if response == gtk.RESPONSE_YES:
                #self._vte2.feed_child("q()\n")
                #self._vte2.feed_child("exit\n")
                self.kill_shell_process(self._vte2_shell_PID)
                self._vte2_shell_PID = -1
                #self.on_vte2_exited(None)
        elif self.vteTabs.get_current_page() == self._vte3_page_number:
            question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "Are you sure you want to close this tab?" )
            response = question_dialog.run()
            question_dialog.destroy()

            if response == gtk.RESPONSE_YES:
                #self._vte3.feed_child("q()\n")
                #self._vte3.feed_child("exit\n")
                self.kill_shell_process(self._vte3_shell_PID)
                self._vte3_shell_PID = -1
                #self.on_vte3_exited(None)

    def restart_R(self):
        question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "Are you sure you want to restart R?\nYou must be at the old R session prompt for this..." )
        response = question_dialog.run()
        question_dialog.destroy()

        if response == gtk.RESPONSE_YES:
            if self.vteTabs.get_current_page() == 0:
                self._vte.feed_child(":q\n")
                self._vte.feed_child("ghci \n") # open R
                self.run_gedit_helper_script(self._vte)
                #if self._plugin.prefs['prompt_color1'] != None or self._plugin.prefs['tab_name_in_prompt'] == True:
                   #self._vte.feed_child(self._plugin.prompt_string(1,self.get_tab_name(1))) # and set the prompt accordingly...
                if self._plugin.prefs['use_current_document_directory']:
                   self.change_vte_R_working_dir_to_the_document(self._vte)
                self.show_messages_and_warnings(self._vte)
            elif self.vteTabs.get_current_page() == self._vte2_page_number:
                self._vte2.feed_child(":q\n")
                self._vte2.feed_child("ghci \n") # open R
                self.run_gedit_helper_script(self._vte2)
                #if self._plugin.prefs['prompt_color2'] != None or self._plugin.prefs['tab_name_in_prompt'] == True:
                   #self._vte2.feed_child(self._plugin.prompt_string(2,self.get_tab_name(2))) # and set the prompt accordingly...
                if self._plugin.prefs['use_current_document_directory']:
                   self.change_vte_R_working_dir_to_the_document(self._vte2)
                self.show_messages_and_warnings(self._vte2)
            elif self.vteTabs.get_current_page() == self._vte3_page_number:
                self._vte3.feed_child(":q\n")
                self._vte3.feed_child("ghci \n") # open R
                self.run_gedit_helper_script(self._vte3)
                #if self._plugin.prefs['prompt_color3'] != None or self._plugin.prefs['tab_name_in_prompt'] == True:
                   #self._vte3.feed_child(self._plugin.prompt_string(3,self.get_tab_name(3))) # and set the prompt accordingly...
                if self._plugin.prefs['use_current_document_directory']:
                   self.change_vte_R_working_dir_to_the_document(self._vte3)
                self.show_messages_and_warnings(self._vte3)

    def start_R(self):
        question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "Are you sure you want to start a new R session?\nYou must be at the shell prompt for this..." )
        response = question_dialog.run()
        question_dialog.destroy()

        if response == gtk.RESPONSE_YES:
            if self.vteTabs.get_current_page() == 0:
                self._vte.feed_child("ghci \n") # open R
                self.run_gedit_helper_script(self._vte)
                #if self._plugin.prefs['prompt_color1'] != None or self._plugin.prefs['tab_name_in_prompt'] == True:
                   #self._vte.feed_child(self._plugin.prompt_string(1,self.get_tab_name(1))) # and set the prompt accordingly...
                if self._plugin.prefs['use_current_document_directory']:
                   self.change_vte_R_working_dir_to_the_document(self._vte)
                self.show_messages_and_warnings(self._vte)
            elif self.vteTabs.get_current_page() == self._vte2_page_number:
                self._vte2.feed_child("ghci \n") # open R
                self.run_gedit_helper_script(self._vte2)
                #if self._plugin.prefs['prompt_color2'] != None or self._plugin.prefs['tab_name_in_prompt'] == True:
                   #self._vte2.feed_child(self._plugin.prompt_string(2,self.get_tab_name(2))) # and set the prompt accordingly...
                if self._plugin.prefs['use_current_document_directory']:
                   self.change_vte_R_working_dir_to_the_document(self._vte2)
                self.show_messages_and_warnings(self._vte2)
            elif self.vteTabs.get_current_page() == self._vte3_page_number:
                self._vte3.feed_child("ghci \n") # open R
                self.run_gedit_helper_script(self._vte3)
                #if self._plugin.prefs['prompt_color3'] != None or self._plugin.prefs['tab_name_in_prompt'] == True:
                   #self._vte3.feed_child(self._plugin.prompt_string(3,self.get_tab_name(3))) # and set the prompt accordingly...
                if self._plugin.prefs['use_current_document_directory']:
                   self.change_vte_R_working_dir_to_the_document(self._vte3)
                self.show_messages_and_warnings(self._vte3)

    def change_R_working_dir(self):
        folder_dialog = gtk.FileChooserDialog("Choose R's working folder", None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
        response = folder_dialog.run()
        if response == gtk.RESPONSE_ACCEPT:
            folder_name = folder_dialog.get_filename()
            # Assume R is working a ready:
            if self.vteTabs.get_current_page() == 0:
                self._vte.feed_child(":cd \""+folder_name+"\" \n")
            elif self.vteTabs.get_current_page() == self._vte2_page_number:
                self._vte2.feed_child(":cd \""+folder_name+"\" \n")
            elif self.vteTabs.get_current_page() == self._vte3_page_number:
                self._vte3.feed_child(":cd \""+folder_name+"\" \n")
            else:
                print( "Unknown R tab!" )
        folder_dialog.destroy()
        
    def change_vte_R_working_dir_to_the_document(self,vte):
        # Change the given vte's R's working folder to the current document's:
        if not self._plugin.window:
            print "Cannot get current window"
            return
            
        doc = self._plugin.window.get_active_document()
        if not doc:
            return
            
        folder_name = doc.get_uri_for_display()
        if not folder_name:
            return
        folder_name = os.path.dirname(folder_name)
            
        # Assume R is working and ready:
        vte.feed_child(":cd \""+folder_name+"\" \n")
        
    def change_R_working_dir_to_the_document(self):
         # Change R's working folder to the current document's:
        if not self._plugin.window:
            print "Cannot get current window"
            return
            
        doc = self._plugin.window.get_active_document()
        if not doc:
            return
            
        folder_name = doc.get_uri_for_display()
        if not folder_name:
            question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Current document has not been saved: cannot change R's working folder to this..." )
            response = question_dialog.run()
            question_dialog.destroy()
            return
        folder_name = os.path.dirname(folder_name)
            
        # Assume R is working and ready:
        if self.vteTabs.get_current_page() == 0:
            self._vte.feed_child(":cd \""+folder_name+"\" \n")
        elif self.vteTabs.get_current_page() == self._vte2_page_number:
            self._vte2.feed_child(":cd \""+folder_name+"\" \n")
        elif self.vteTabs.get_current_page() == self._vte3_page_number:
            self._vte3.feed_child(":cd \""+folder_name+"\" \n")
        else:
            print( "Unknown R tab!" )
        
    def on_R_load_workspace(self):
        file_dialog = gtk.FileChooserDialog("Open R Workspace", None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
        
        filter = gtk.FileFilter()
        filter.set_name("R worksapce")
        filter.add_pattern("*.RData")
        filter.add_pattern("*.R")
        file_dialog.add_filter(filter)

        filter = gtk.FileFilter()
        filter.set_name("All files")
        filter.add_pattern("*")
        file_dialog.add_filter(filter)

        response = file_dialog.run()
        if response == gtk.RESPONSE_ACCEPT:
            file_name = file_dialog.get_filename()
            do_send_to_R( "load( \""+file_name+"\", .GlobalEnv )\n", self, False, self._plugin.prefs['max_lines_as_text'] )
        file_dialog.destroy()

    def on_R_save_workspace(self):
        file_dialog = gtk.FileChooserDialog("Save R Workspace", None, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
        
        filter = gtk.FileFilter()
        filter.set_name("R worksapce")
        filter.add_pattern("*.RData")
        filter.add_pattern("*.R")
        file_dialog.add_filter(filter)

        filter = gtk.FileFilter()
        filter.set_name("All files")
        filter.add_pattern("*")
        file_dialog.add_filter(filter)

        file_dialog.set_current_name(".RData")
        
        file_dialog.set_do_overwrite_confirmation( True )

        response = file_dialog.run()
        if response == gtk.RESPONSE_ACCEPT:
            file_name = file_dialog.get_filename()
            do_send_to_R( "save( list = ls(all=TRUE), file = \""+file_name+"\" )\n", self, False, self._plugin.prefs['max_lines_as_text'] )
        file_dialog.destroy()


########################################################
#                 End GeditTerminal                    #
########################################################


# Send given text to R
def do_send_to_R( text_to_send, R_widget, as_source, max_lines_direct_send=50 ):
    if not R_widget:
        print "No R console open?"
        return
        
    #print R_widget._plugin.prefs['echo_commands']
        
    if as_source | (text_to_send.count("\n") > max_lines_direct_send):
        # Write the text to a temp file and call source():
        R_file = open( '/tmp/haskellFile.hs', 'w' )
        R_file.write( text_to_send )
        R_file.close()
        R_widget.send_command(':l "/tmp/haskellFile.hs" \n') 
    else:
        # Pipe directly to R:
        R_widget.send_command(text_to_send) 

# Check is a given line is empty or just a comment:
def is_empty_comment_line( line ):
    # Skip all white spaces:
    line_stripped = line.strip();
    return (len(line_stripped) == 0) or (line_stripped[0] == '#');

class RCtrlWindowHelper:
    def __init__(self, plugin, window):
        self._window = window
        self._plugin = plugin
        self.datadir = plugin.get_data_dir();
        self.R_widget = None
        self.Detached_R_Dialog = None
        
        # Init the RWizards:
        self.rwizards = RWizardEngine(self)

        # Insert menu items
        self._insert_menu()
        
        # And the R structure panel tab:
        self._rstructurepanel = RStructurePanel(self)

    def deactivate(self):
        # Remove any installed menu items
        self._remove_menu()

        self._window = None
        self._plugin = None
        self._action_group = None

    def _insert_menu(self):
        # Get the GtkUIManager
        manager = self._window.get_ui_manager()

        R_action = gtk.Action("R","R","R plugin commands",None)
        R_action_group = gtk.ActionGroup("R")
        R_action_group.add_action(R_action)
        manager.insert_action_group(R_action_group, -1)

        # Create a new action group
        self._action_group = gtk.ActionGroup("RCtrlPluginActions")
        self._action_group.add_actions([("RCtrlLine", None, _("Run current line through R..."),
                                         self._plugin.prefs['shortcut_RCtrlLine'], _("Run current line through R..."),
                                         self.on_send_line_to_R),
                                        ("RCtrlSel", None, _("Run selection through R..."),
                                         self._plugin.prefs['shortcut_RCtrlSel'], _("Run selection through R..."),
                                         self.on_send_selection_to_R),
                                        ("RCtrlAll", None, _("Run whole file through R..."),
                                         self._plugin.prefs['shortcut_RCtrlAll'], _("Run whole file through R..."),
                                         self.on_send_file_to_R),
                                        ("RCtrlBlock1Run", None, _("Run block 1 through R..."),
                                         self._plugin.prefs['shortcut_RCtrlBlock1Run'], _("Run block 1 through R..."),
                                         self.on_send_block1_to_R),
                                        ("RCtrlBlock1Def", None, _("Define block 1..."),
                                         self._plugin.prefs['shortcut_RCtrlBlock1Def'], _("Define block 1..."),
                                         self.on_define_block1),
                                        ("RCtrlBlock2Run", None, _("Run block 2 through R..."),
                                         self._plugin.prefs['shortcut_RCtrlBlock2Run'], _("Run block 2 through R..."),
                                         self.on_send_block2_to_R),
                                        ("RCtrlBlock2Def", None, _("Define block 2..."),
                                         self._plugin.prefs['shortcut_RCtrlBlock2Def'], _("Define block 2..."),
                                         self.on_define_block2),
                                        ("RCtrlNewTab", None, _("Create new R workspace tab..."),
                                         self._plugin.prefs['shortcut_RCtrlNewTab'], _("Create new R workspace tab (max 3 tabs allowed)..."),
                                         self.on_create_new_R_tab),
                                        ("RCtrlConfig", None, _("Configure R interface"),
                                         self._plugin.prefs['shortcut_RCtrlConfig'], _("Configure R interface"),
                                         self.on_R_config_dialog),
                                        ("RCtrlUpdate", None, _("Check for updates"),
                                         None, _("Check for updates"),
                                         self.on_check_for_updates),
                                        #("RCtrlLoadWorkspace", None, _("Load R Workspace"),
                                        # self._plugin.prefs['shortcut_RCtrlLoadWorkspace'], _("Load R Workspace"),
                                        # self.on_R_load_workspace),
                                        #("RCtrlSaveWorkspace", None, _("Save R Workspace"),
                                        # self._plugin.prefs['shortcut_RCtrlSaveWorkspace'], _("Save R Workspace"),
                                        # self.on_R_save_workspace),
                                        ("RCtrlLandmark", None, _("Insert Landmark Comment"),
                                         None, _("Insert Landmark Comment"),
                                         self.on_R_LandmarkComment),
                                        ("RCtrlWizards", None, _("Wizards"),
                                         None, _("Wizards"),
                                         self.on_R_wizards),
                                        #("RCtrlHelpSel", None, _("Search selection in R help"),
                                        # self._plugin.prefs['shortcut_RCtrlHelpSel'], _("Search selection in R help"),
                                        # self.on_R_search_selection_in_help),
                                        #("RCtrlShowSel", None, _("Inspect selection using showData()"),
                                        # self._plugin.prefs['shortcut_RCtrlShowSel'], _("Inspect selection using showData()"),
                                        # self.on_R_show_selection),
                                        #("RCtrlEditSel", None, _("Edit selection using fix()"),
                                        # self._plugin.prefs['shortcut_RCtrlEditSel'], _("Edit selection using fix()"),
                                        # self.on_R_edit_selection),
                                        ("RCtrlShowHide", None, _("Show/hide toolbar"),
                                         None, _("Show/hide toolbar"),
                                         self.on_R_showhide),
                                        ("RCtrlAttach", None, _("Attach/detach R Console"),
                                         self._plugin.prefs['shortcut_RCtrlAttach'], _("Attach/detach R Console"),
                                         self.on_R_attach),
                                        ("RCtrlClose", None, _("Close R Console"),
                                         self._plugin.prefs['shortcut_RCtrlClose'], _("Close R Console"),
                                         self.on_R_close),
                                        ("RCtrlHelpRCtrl", None, _("Help"),
                                         None, _("Help"),
                                         self.on_R_help),
                                        ("RCtrlAbout", None, _("About"),
                                         None, _("About"),
                                         self.on_R_about)])
                                         
        # Insert the action group
        manager.insert_action_group(self._action_group, 0)

        # Merge the UI
        self._ui_id = manager.add_ui_from_string(ui_str)

        # Make them insensitive and invisible, depending on the action:
        manager.get_action("/ToolBar/RCtrlLine").set_sensitive(False)
        manager.get_action("/ToolBar/RCtrlSel").set_sensitive(False)
        manager.get_action("/ToolBar/RCtrlAll").set_sensitive(False)
        manager.get_action("/ToolBar/RCtrlNewTab").set_sensitive(True)
        #manager.get_action("/ToolBar/RCtrlConfig").set_sensitive(True)
        manager.get_action("/MenuBar/R/RCtrlBlock1Run").set_sensitive(False)
        manager.get_action("/MenuBar/R/RCtrlBlock2Run").set_sensitive(False)
        #manager.get_action("/MenuBar/R/RCtrlLoadWorkspace").set_sensitive(False)
        #manager.get_action("/MenuBar/R/RCtrlSaveWorkspace").set_sensitive(False)
        #manager.get_action("/MenuBar/R/RCtrlHelpSel").set_sensitive(False)
        #manager.get_action("/MenuBar/R/RCtrlShowSel").set_sensitive(False)
        #manager.get_action("/MenuBar/R/RCtrlEditSel").set_sensitive(False)
        manager.get_action("/MenuBar/R/RCtrlAttach").set_sensitive(False)
        manager.get_action("/MenuBar/R/RCtrlClose").set_sensitive(False)

        # Add the icons to the toolbar items:
        RCtrlLine_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/run_line.png" , 24, 24)
        RCtrlLine_icon.set_from_pixbuf(pixbuf)
        RCtrlLine_icon.show()
        RCtrlLine_toolitem = manager.get_widget("/ToolBar/RCtrlLine")
        RCtrlLine_toolitem.set_icon_widget(RCtrlLine_icon)
        RCtrlLine_toolitem.show()
        RCtrlLine_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/run_line.png" , 24, 24)
        RCtrlLine_icon.set_from_pixbuf(pixbuf)
        RCtrlLine_icon.show()
        RCtrlLine_menuitem = manager.get_widget("/MenuBar/R/RCtrlLine")
        RCtrlLine_menuitem.set_image(RCtrlLine_icon)
        RCtrlLine_menuitem.show()

        RCtrlSel_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/run_selection.png" , 24, 24)
        RCtrlSel_icon.set_from_pixbuf(pixbuf)
        RCtrlSel_icon.show()
        RCtrlSel_toolitem = manager.get_widget("/ToolBar/RCtrlSel")
        RCtrlSel_toolitem.set_icon_widget(RCtrlSel_icon)
        RCtrlSel_toolitem.show()
        RCtrlSel_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/run_selection.png" , 24, 24)
        RCtrlSel_icon.set_from_pixbuf(pixbuf)
        RCtrlSel_icon.show()
        RCtrlSel_menuitem = manager.get_widget("/MenuBar/R/RCtrlSel")
        RCtrlSel_menuitem.set_image(RCtrlSel_icon)
        RCtrlSel_menuitem.show()

        RCtrlAll_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/run_all.png" , 24, 24)
        RCtrlAll_icon.set_from_pixbuf(pixbuf)
        RCtrlAll_icon.show()
        RCtrlAll_toolitem = manager.get_widget("/ToolBar/RCtrlAll")
        RCtrlAll_toolitem.set_icon_widget(RCtrlAll_icon)
        RCtrlAll_toolitem.show()
        RCtrlAll_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/run_all.png" , 24, 24)
        RCtrlAll_icon.set_from_pixbuf(pixbuf)
        RCtrlAll_icon.show()
        RCtrlAll_menuitem = manager.get_widget("/MenuBar/R/RCtrlAll")
        RCtrlAll_menuitem.set_image(RCtrlAll_icon)
        RCtrlAll_menuitem.show()

        RCtrlBlock1Run_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block1_run.png" , 24, 24)
        RCtrlBlock1Run_icon.set_from_pixbuf(pixbuf)
        RCtrlBlock1Run_icon.show()
        RCtrlBlock1Run_toolitem = manager.get_widget("/ToolBar/RCtrlBlock1Run")
        RCtrlBlock1Run_toolitem.set_icon_widget(RCtrlBlock1Run_icon)
        RCtrlBlock1Run_toolitem.show()
        RCtrlBlock1Run_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block1_run.png" , 24, 24)
        RCtrlBlock1Run_icon.set_from_pixbuf(pixbuf)
        RCtrlBlock1Run_icon.show()
        RCtrlBlock1Run_menuitem = manager.get_widget("/MenuBar/R/RCtrlBlock1Run")
        RCtrlBlock1Run_menuitem.set_image(RCtrlBlock1Run_icon)
        RCtrlBlock1Run_menuitem.show()

        RCtrlBlock1Def_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block1_def.png" , 24, 24)
        RCtrlBlock1Def_icon.set_from_pixbuf(pixbuf)
        RCtrlBlock1Def_icon.show()
        RCtrlBlock1Def_toolitem = manager.get_widget("/ToolBar/RCtrlBlock1Def")
        RCtrlBlock1Def_toolitem.set_icon_widget(RCtrlBlock1Def_icon)
        RCtrlBlock1Def_toolitem.show()
        RCtrlBlock1Def_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block1_def.png" , 24, 24)
        RCtrlBlock1Def_icon.set_from_pixbuf(pixbuf)
        RCtrlBlock1Def_icon.show()
        RCtrlBlock1Def_menuitem = manager.get_widget("/MenuBar/R/RCtrlBlock1Def")
        RCtrlBlock1Def_menuitem.set_image(RCtrlBlock1Def_icon)
        RCtrlBlock1Def_menuitem.show()

        RCtrlBlock2Run_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block2_run.png" , 24, 24)
        RCtrlBlock2Run_icon.set_from_pixbuf(pixbuf)
        RCtrlBlock2Run_icon.show()
        RCtrlBlock2Run_toolitem = manager.get_widget("/ToolBar/RCtrlBlock2Run")
        RCtrlBlock2Run_toolitem.set_icon_widget(RCtrlBlock2Run_icon)
        RCtrlBlock2Run_toolitem.show()
        RCtrlBlock2Run_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block2_run.png" , 24, 24)
        RCtrlBlock2Run_icon.set_from_pixbuf(pixbuf)
        RCtrlBlock2Run_icon.show()
        RCtrlBlock2Run_menuitem = manager.get_widget("/MenuBar/R/RCtrlBlock2Run")
        RCtrlBlock2Run_menuitem.set_image(RCtrlBlock2Run_icon)
        RCtrlBlock2Run_menuitem.show()

        RCtrlBlock2Def_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block2_def.png" , 24, 24)
        RCtrlBlock2Def_icon.set_from_pixbuf(pixbuf)
        RCtrlBlock2Def_icon.show()
        RCtrlBlock2Def_toolitem = manager.get_widget("/ToolBar/RCtrlBlock2Def")
        RCtrlBlock2Def_toolitem.set_icon_widget(RCtrlBlock2Def_icon)
        RCtrlBlock2Def_toolitem.show()
        RCtrlBlock2Def_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block2_def.png" , 24, 24)
        RCtrlBlock2Def_icon.set_from_pixbuf(pixbuf)
        RCtrlBlock2Def_icon.show()
        RCtrlBlock2Def_menuitem = manager.get_widget("/MenuBar/R/RCtrlBlock2Def")
        RCtrlBlock2Def_menuitem.set_image(RCtrlBlock2Def_icon)
        RCtrlBlock2Def_menuitem.show()

        RCtrlNewTab_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/new_workspace.png" , 24, 24)
        RCtrlNewTab_icon.set_from_pixbuf(pixbuf)
        RCtrlNewTab_icon.show()
        RCtrlNewTab_toolitem = manager.get_widget("/ToolBar/RCtrlNewTab")
        RCtrlNewTab_toolitem.set_icon_widget(RCtrlNewTab_icon)
        RCtrlNewTab_toolitem.show()
        RCtrlNewTab_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/new_workspace.png" , 24, 24)
        RCtrlNewTab_icon.set_from_pixbuf(pixbuf)
        RCtrlNewTab_icon.show()
        RCtrlNewTab_menuitem = manager.get_widget("/MenuBar/R/RCtrlNewTab")
        RCtrlNewTab_menuitem.set_image(RCtrlNewTab_icon)
        RCtrlNewTab_menuitem.show()

        #RCtrlConfig_icon = gtk.Image()
        #pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/config.png" , 24, 24)
        #RCtrlConfig_icon.set_from_pixbuf(pixbuf)
        #RCtrlConfig_icon.show()
        #RCtrlConfig_toolitem = manager.get_widget("/ToolBar/RCtrlConfig")
        #RCtrlConfig_toolitem.set_icon_widget(RCtrlConfig_icon)
        #RCtrlConfig_toolitem.show()
        RCtrlConfig_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/config.png" , 24, 24)
        RCtrlConfig_icon.set_from_pixbuf(pixbuf)
        RCtrlConfig_icon.show()
        RCtrlConfig_menuitem = manager.get_widget("/MenuBar/R/RCtrlConfig")
        RCtrlConfig_menuitem.set_image(RCtrlConfig_icon)
        RCtrlConfig_menuitem.show()

        RCtrlAttach_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/attachdetach.png" , 24, 24)
        RCtrlAttach_icon.set_from_pixbuf(pixbuf)
        RCtrlAttach_icon.show()
        RCtrlAttach_menuitem = manager.get_widget("/MenuBar/R/RCtrlAttach")
        RCtrlAttach_menuitem.set_image(RCtrlAttach_icon)
        RCtrlAttach_menuitem.show()

        RCtrlClose_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/closeRconsole.png" , 24, 24)
        RCtrlClose_icon.set_from_pixbuf(pixbuf)
        RCtrlClose_icon.show()
        RCtrlClose_menuitem = manager.get_widget("/MenuBar/R/RCtrlClose")
        RCtrlClose_menuitem.set_image(RCtrlClose_icon)
        RCtrlClose_menuitem.show()

        RCtrlLandmark_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/landmark_comment.png" , 24, 24)
        RCtrlLandmark_icon.set_from_pixbuf(pixbuf)
        RCtrlLandmark_icon.show()
        RCtrlLandmark_menuitem = manager.get_widget("/MenuBar/R/RCtrlLandmark")
        RCtrlLandmark_menuitem.set_image(RCtrlLandmark_icon)
        RCtrlLandmark_menuitem.show()

        #RCtrlHelpSel_icon = gtk.Image()
        #pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/selection_help.png" , 24, 24)
        #RCtrlHelpSel_icon.set_from_pixbuf(pixbuf)
        #RCtrlHelpSel_icon.show()
        #RCtrlHelpSel_menuitem = manager.get_widget("/MenuBar/R/RCtrlHelpSel")
        #RCtrlHelpSel_menuitem.set_image(RCtrlHelpSel_icon)
        #RCtrlHelpSel_menuitem.show()
        #
        #RCtrlShowSel_icon = gtk.Image()
        #pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/selection_showdata.png" , 24, 24)
        #RCtrlShowSel_icon.set_from_pixbuf(pixbuf)
        #RCtrlShowSel_icon.show()
        #RCtrlShowSel_menuitem = manager.get_widget("/MenuBar/R/RCtrlShowSel")
        #RCtrlShowSel_menuitem.set_image(RCtrlShowSel_icon)
        #RCtrlShowSel_menuitem.show()
        #
        #RCtrlEditSel_icon = gtk.Image()
        #pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/selection_editdata.png" , 24, 24)
        #RCtrlEditSel_icon.set_from_pixbuf(pixbuf)
        #RCtrlEditSel_icon.show()
        #RCtrlEditSel_menuitem = manager.get_widget("/MenuBar/R/RCtrlEditSel")
        #RCtrlEditSel_menuitem.set_image(RCtrlEditSel_icon)
        #RCtrlEditSel_menuitem.show()

        RCtrlHelpRCtrl_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/help.png" , 24, 24)
        RCtrlHelpRCtrl_icon.set_from_pixbuf(pixbuf)
        RCtrlHelpRCtrl_icon.show()
        RCtrlHelpRCtrl_menuitem = manager.get_widget("/MenuBar/R/RCtrlHelpRCtrl")
        RCtrlHelpRCtrl_menuitem.set_image(RCtrlHelpRCtrl_icon)
        RCtrlHelpRCtrl_menuitem.show()

        RCtrlAbout_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/Rgedit-icon.png" , 24, 24)
        RCtrlAbout_icon.set_from_pixbuf(pixbuf)
        RCtrlAbout_icon.show()
        RCtrlAbout_menuitem = manager.get_widget("/MenuBar/R/RCtrlAbout")
        RCtrlAbout_menuitem.set_image(RCtrlAbout_icon)
        RCtrlAbout_menuitem.show()

        #RCtrlLoadWorkspace_icon = gtk.Image()
        #pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/load_workspace.png" , 24, 24)
        #RCtrlLoadWorkspace_icon.set_from_pixbuf(pixbuf)
        #RCtrlLoadWorkspace_icon.show()
        #RCtrlLoadWorkspace_menuitem = manager.get_widget("/MenuBar/R/RCtrlLoadWorkspace")
        #RCtrlLoadWorkspace_menuitem.set_image(RCtrlLoadWorkspace_icon)
        #RCtrlLoadWorkspace_menuitem.show()
        #
        #RCtrlSaveWorkspace_icon = gtk.Image()
        #pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/save_workspace.png" , 24, 24)
        #RCtrlSaveWorkspace_icon.set_from_pixbuf(pixbuf)
        #RCtrlSaveWorkspace_icon.show()
        #RCtrlSaveWorkspace_menuitem = manager.get_widget("/MenuBar/R/RCtrlSaveWorkspace")
        #RCtrlSaveWorkspace_menuitem.set_image(RCtrlSaveWorkspace_icon)
        #RCtrlSaveWorkspace_menuitem.show()

        # Insert the show/hide toolitem submenu:
        ShowHideMenu = manager.get_widget("/MenuBar/R/RCtrlShowHide")
        ShowHideSubmenu = gtk.Menu()
        ShowHideLine = gtk.CheckMenuItem("Run current line through R...")
        ShowHideLine.connect("toggled",self.on_toggle_ShowHideLine)
        ShowHideLine.set_active(self._plugin.prefs['show_run_line'])
        ShowHideLine.show()
        self.on_toggle_ShowHideLine(ShowHideLine)

        ShowHideSel = gtk.CheckMenuItem("Run current selection through R...")
        ShowHideSel.connect("toggled",self.on_toggle_ShowHideSel)
        ShowHideSel.set_active(self._plugin.prefs['show_run_sel'])
        ShowHideSel.show()
        self.on_toggle_ShowHideSel(ShowHideSel)

        ShowHideAll = gtk.CheckMenuItem("Run whole file through R...")
        ShowHideAll.connect("toggled",self.on_toggle_ShowHideAll)
        ShowHideAll.set_active(self._plugin.prefs['show_run_all'])
        ShowHideAll.show()
        self.on_toggle_ShowHideAll(ShowHideAll)

        ShowHideBlock1Run = gtk.CheckMenuItem("Run block 1 through R...")
        ShowHideBlock1Run.connect("toggled",self.on_toggle_ShowHideBlock1Run)
        ShowHideBlock1Run.set_active(self._plugin.prefs['show_run_block1'])
        ShowHideBlock1Run.show()
        self.on_toggle_ShowHideBlock1Run(ShowHideBlock1Run)

        ShowHideBlock1Def = gtk.CheckMenuItem("Define block 1...")
        ShowHideBlock1Def.connect("toggled",self.on_toggle_ShowHideBlock1Def)
        ShowHideBlock1Def.set_active(self._plugin.prefs['show_def_block1'])
        ShowHideBlock1Def.show()
        self.on_toggle_ShowHideBlock1Def(ShowHideBlock1Def)

        ShowHideBlock2Run = gtk.CheckMenuItem("Run block 2 through R...")
        ShowHideBlock2Run.connect("toggled",self.on_toggle_ShowHideBlock2Run)
        ShowHideBlock2Run.set_active(self._plugin.prefs['show_run_block2'])
        ShowHideBlock2Run.show()
        self.on_toggle_ShowHideBlock2Run(ShowHideBlock2Run)

        ShowHideBlock2Def = gtk.CheckMenuItem("Define block 2...")
        ShowHideBlock2Def.connect("toggled",self.on_toggle_ShowHideBlock2Def)
        ShowHideBlock2Def.set_active(self._plugin.prefs['show_def_block2'])
        ShowHideBlock2Def.show()
        self.on_toggle_ShowHideBlock2Def(ShowHideBlock2Def)

        ShowHideNewTab = gtk.CheckMenuItem("Create new R workspace tab...")
        ShowHideNewTab.connect("toggled",self.on_toggle_ShowHideNewTab)
        ShowHideNewTab.set_active(self._plugin.prefs['show_new_tab'])
        ShowHideNewTab.show()
        self.on_toggle_ShowHideNewTab(ShowHideNewTab)

        ShowHideSubmenu.attach(ShowHideLine,0,1,0,1)
        ShowHideSubmenu.attach(ShowHideSel,0,1,1,2)
        ShowHideSubmenu.attach(ShowHideAll,0,1,2,3)
        ShowHideSubmenu.attach(ShowHideBlock1Run,0,1,3,4)
        ShowHideSubmenu.attach(ShowHideBlock1Def,0,1,4,5)
        ShowHideSubmenu.attach(ShowHideBlock2Run,0,1,5,6)
        ShowHideSubmenu.attach(ShowHideBlock2Def,0,1,6,7)
        ShowHideSubmenu.attach(ShowHideNewTab,0,1,7,8)
        ShowHideMenu.set_submenu(ShowHideSubmenu)
        
        #Fill in the wizards menu:
        self.fill_in_wizards_menu(manager.get_widget("/MenuBar/R/RCtrlWizards"))

        # Make the attach menu a check menu:
        self.RConsole_attach = not self._plugin.prefs['RConsole_start_attached']
        self.on_R_attach(None)

        # Also create the bottom panel widget if autostart is enabled:
        if self._plugin.prefs['autostart_R_console'] == True:
            self.createRGeditTerminal()

    #Fill in the wizards menu:
    def fill_in_wizards_menu(self,WizardsMenu):
        # Create a data structure which retains the menu (sub)paths and the associated menu item (to avoid menu duplications)
        # This is, in fact, a dictionary having as the key the path
        self.submenu_dictionary = {}
        
        if len(self.rwizards.wizards) > 0:
            WizardsSubmenu = gtk.Menu()
            
            # The About... menu first:
            about_menu_item = gtk.ImageMenuItem("About Rwizards...")
            try:
                menu_icon = gtk.Image()
                pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.rwizards.wizards[1]._rwizardengine.path+"wizard.png",16,16)
                menu_icon.set_from_pixbuf(pixbuf)
                menu_icon.show()
                about_menu_item.set_image(menu_icon)
            except:
                pass
            about_menu_item.show()
            about_menu_item.connect("activate",self.on_about_rwizards,self.rwizards.wizards[1]._rwizardengine.path+"wizard.png")
            WizardsSubmenu.append(about_menu_item)
            
            # The submenus:
            for wizard in self.rwizards.wizards:
                # Make sure a reasonable menu path exists and return the actual menu path:
                self.create_submenu_path( WizardsSubmenu, wizard.ActualMenu, wizard.Description, wizard._rwizardengine.path+wizard.ActualIcon, 1 )
            WizardsMenu.set_submenu(WizardsSubmenu)
            menu_icon = gtk.Image()
            pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(wizard._rwizardengine.path+"wizard.png",16,16)
            menu_icon.set_from_pixbuf(pixbuf)
            menu_icon.show()
            WizardsMenu.set_image(menu_icon)
            
    def create_submenu_path(self,current_submenu,submenu_path,item_description,item_icon,cur_depth):
        # Parse the submenu_path and keep at most max_submenu_path_depth levels:
        splitted_path = submenu_path.split("/")
        if cur_depth > 5 or cur_depth >= len(splitted_path):
            actual_menu_item = gtk.ImageMenuItem(item_description)
            try:
                menu_icon = gtk.Image()
                pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(item_icon,16,16)
                menu_icon.set_from_pixbuf(pixbuf)
                menu_icon.show()
                actual_menu_item.set_image(menu_icon)
            except:
                pass
            actual_menu_item.show()
            actual_menu_item.connect("activate",self.on_wizard_activated,item_description)
            current_submenu.append(actual_menu_item)
            return

        curr_item = splitted_path[cur_depth]
        #print "Attempting to create wizard submenu:" + curr_item
        
        # See if the menu path aredy exists:
        cur_sub_path = "/".join(splitted_path[:(cur_depth+1)])
        #print "get_widget: /MenuBar/R/RCtrlWizards"+cur_sub_path
        
        # Recursion:
        already_defined = False
        if not cur_sub_path in self.submenu_dictionary:
            # Create it:
            submenu_item = gtk.MenuItem(curr_item)
            submenu_item.show()
            submenu_submenu = gtk.Menu()
            current_submenu.append(submenu_item)
            self.submenu_dictionary[cur_sub_path] = submenu_submenu
        else:
            # Reuse it:
            submenu_submenu = self.submenu_dictionary[cur_sub_path]
            already_defined = True
        
        self.create_submenu_path(submenu_submenu,submenu_path,item_description,item_icon,cur_depth+1)
        if not already_defined:
            submenu_item.set_submenu(submenu_submenu)
        return
        
        
    def on_wizard_activated(self,widget,data):
        # A wizard was clicked and data contains its description:
        # Identify the wizard and call it:
        found = False
        for wizard in self.rwizards.wizards:
            if wizard.Description == data:
                # Call the wizard:
                wizard.run()
                found = True
                break
        if not found:
            print "Something fishy: cannot find the wizard with description \"" + data + "\"..."
            
    def on_about_rwizards(self,widget,icon):
        # Get the current version of the official wizards pack:
        wizards_pack_version_file = open( self._plugin.get_data_dir() + str("/Wizards/wizards.version"), "rt" )
        wizards_current_version = wizards_pack_version_file.read()
        wizards_current_version = wizards_current_version.strip()
        wizards_pack_version_file.close()
        
        # Display the About Rwizards dialog:
        about_dialog = gtk.AboutDialog()
        about_dialog.set_name("RWizards official package")
        about_dialog.set_version(wizards_current_version)
        about_dialog.set_copyright("(c) 2009,2010, Dan Dediu")    
        about_dialog.set_comments("A set of predefined Rwizards")
        about_dialog.set_license("""
    Rwizards official package: a set of wizards for rgedit
    Copyright (C) 2009  Dan Dediu

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
""")
        about_dialog.set_website("http://sourceforge.net/projects/rgedit/")
        about_dialog.set_authors("") 
        about_dialog.set_documenters("")
        about_dialog.set_artists("")
        about_dialog.set_translator_credits("")
        about_dialog.set_logo(gtk.gdk.pixbuf_new_from_file(icon))
        
        about_dialog.show()
        about_dialog.run()
        about_dialog.destroy()
                    

    def createRGeditTerminal(self):
        self.R_widget = RGeditTerminal(self._plugin)
        self.R_widget._window = self._window

        #print self._plugin.prefs['RConsole_start_attached']
        self.bottom_panel_dummy_hbox = None
        if self._plugin.prefs['RConsole_start_attached'] == False:
            R_icon = gtk.Image()
            R_icon.set_from_file(self.datadir+"/Rgedit-icon24.png")
            self.bottom_panel_dummy_hbox = gtk.HBox()
            self.bottom_panel_dummy_hbox.show()
            self.bottom_panel_dummy_hbox.pack_start(self.R_widget,True,True)
            self.R_widget.show()
            self._window.get_bottom_panel().add_item(self.bottom_panel_dummy_hbox,"R Console",R_icon)
            self._window.get_bottom_panel().set_property("visible",True)
        elif self.Detached_R_Dialog != None:
            self.R_widget.show()
            try:
                self.Detached_R_Dialog.get_content_area().pack_start(self.R_widget,True,True)
            except:
                self.Detached_R_Dialog.get_child().pack_start(self.R_widget,True,True)            
            self.Detached_R_Dialog.show()
        else:
            # Create the dialog to embed the detached R console:
            #self.Detached_R_Dialog = gtk.Dialog( "Detached R console", self._window, gtk.DIALOG_DESTROY_WITH_PARENT, None );
            self.Detached_R_Dialog = gtk.Window( gtk.WINDOW_TOPLEVEL )
            self.Detached_R_Dialog.set_title( "Detached R console" )
            self.Detached_R_Dialog.set_destroy_with_parent( True )
            self.Detached_R_Dialog.connect('delete_event', self.on_R_Dialog_close)
            self.Detached_R_Dialog.connect('configure_event', self.on_R_Dialog_configure)
            self.Detached_R_Dialog.set_icon(gtk.gdk.pixbuf_new_from_file(self.datadir+"/Rgedit-icon24.png"))
            if self._plugin.prefs['RConsole_detached_x'] != -1 and self._plugin.prefs['RConsole_detached_y'] != -1:
                self.Detached_R_Dialog.move(self._plugin.prefs['RConsole_detached_x'],self._plugin.prefs['RConsole_detached_y'])
            if self._plugin.prefs['RConsole_detached_width'] == -1:
                self._plugin.prefs['RConsole_detached_width'] = 100
            if self._plugin.prefs['RConsole_detached_height'] == -1:
                self._plugin.prefs['RConsole_detached_height'] = 100
            self.Detached_R_Dialog.resize(self._plugin.prefs['RConsole_detached_width'],self._plugin.prefs['RConsole_detached_height'])
            if self.R_widget != None:
                dummyHBox = gtk.HBox()
                dummyHBox.show()
                dummyHBox.pack_start(self.R_widget,True,True)
                self.R_widget.show()
                #try:
                #    self.Detached_R_Dialog.get_content_area().pack_start(dummyHBox,True,True)
                #except:
                #    self.Detached_R_Dialog.get_child().pack_start(dummyHBox,True,True)                            
                self.Detached_R_Dialog.add(dummyHBox)
            self.Detached_R_Dialog.show()

        self.R_widget.send_command("ghci \n") # open R
        self.R_widget.run_gedit_helper_script(self.R_widget._vte)
        #if self._plugin.prefs['prompt_color1'] != None or self._plugin.prefs['tab_name_in_prompt'] == True:
            #self.R_widget.send_command(self._plugin.prompt_string(1,self.R_widget.get_tab_name(1))) # and set the prompt accordingly...
        if self._plugin.prefs['use_current_document_directory']:
            self.R_widget.change_vte_R_working_dir_to_the_document(self.R_widget._vte)
        self.R_widget.show_messages_and_warnings(self.R_widget._vte)

        # Sensitivity:
        manager = self._window.get_ui_manager()
        manager.get_action("/ToolBar/RCtrlLine").set_sensitive(True)
        manager.get_action("/ToolBar/RCtrlSel").set_sensitive(True)
        manager.get_action("/ToolBar/RCtrlAll").set_sensitive(True)
        manager.get_action("/ToolBar/RCtrlNewTab").set_sensitive(True)
        #manager.get_action("/ToolBar/RCtrlConfig").set_sensitive(True)
        manager.get_action("/MenuBar/R/RCtrlAttach").set_sensitive(True)
        manager.get_action("/MenuBar/R/RCtrlBlock1Run").set_sensitive(True)
        manager.get_action("/MenuBar/R/RCtrlBlock2Run").set_sensitive(True)
        #manager.get_action("/MenuBar/R/RCtrlLoadWorkspace").set_sensitive(True)
        #manager.get_action("/MenuBar/R/RCtrlSaveWorkspace").set_sensitive(True)
        #manager.get_action("/MenuBar/R/RCtrlHelpSel").set_sensitive(True)
        #manager.get_action("/MenuBar/R/RCtrlShowSel").set_sensitive(True)
        #manager.get_action("/MenuBar/R/RCtrlEditSel").set_sensitive(True)
        manager.get_action("/MenuBar/R/RCtrlClose").set_sensitive(True)

    def create_R_detached_dialog(self):
        # Create the dialog to embed the detached R console:
        #self.Detached_R_Dialog = gtk.Dialog( "Detached R console", self._window, gtk.DIALOG_DESTROY_WITH_PARENT, None );
        self.Detached_R_Dialog = gtk.Window( gtk.WINDOW_TOPLEVEL )
        self.Detached_R_Dialog.set_title( "Detached R console" )
        self.Detached_R_Dialog.set_destroy_with_parent( True )
        self.Detached_R_Dialog.connect('delete_event', self.on_R_Dialog_close)
        self.Detached_R_Dialog.connect('configure_event', self.on_R_Dialog_configure)
        self.Detached_R_Dialog.set_icon(gtk.gdk.pixbuf_new_from_file(self.datadir+"/Rgedit-icon24.png"))
        if self._plugin.prefs['RConsole_detached_x'] != -1 and self._plugin.prefs['RConsole_detached_y'] != -1:
            self.Detached_R_Dialog.move(self._plugin.prefs['RConsole_detached_x'],self._plugin.prefs['RConsole_detached_y'])
        if self._plugin.prefs['RConsole_detached_width'] == -1:
            self._plugin.prefs['RConsole_detached_width'] = 100
        if self._plugin.prefs['RConsole_detached_height'] == -1:
            self._plugin.prefs['RConsole_detached_height'] = 100
        self.Detached_R_Dialog.resize(self._plugin.prefs['RConsole_detached_width'],self._plugin.prefs['RConsole_detached_height'])
        if self.R_widget != None:
            dummyHBox = gtk.HBox()
            dummyHBox.show()
            self.R_widget.reparent(dummyHBox)
            #try:
            #    self.Detached_R_Dialog.get_content_area().pack_start(dummyHBox,True,True)
            #except:
            #    self.Detached_R_Dialog.get_child().pack_start(dummyHBox,True,True)
            self.Detached_R_Dialog.add(dummyHBox)
        self.Detached_R_Dialog.show()
        if self.bottom_panel_dummy_hbox != None:
            self._window.get_bottom_panel().remove_item(self.bottom_panel_dummy_hbox)

    def destroy_R_detached_dialog(self):
        self.on_R_Dialog_close(None,None)
        
        # Destroy the dialog to embed the detached R console:
        self.Detached_R_Dialog.destroy()
        self.Detached_R_Dialog = None

    def on_R_Dialog_close(self,data1,data2):
        if data1 != None or data2 != None:
            self.on_R_attach(None)
        R_icon = gtk.Image()
        R_icon.set_from_file(self.datadir+"/Rgedit-icon24.png")
        self.bottom_panel_dummy_hbox = gtk.HBox()
        self.bottom_panel_dummy_hbox.show()
        self.R_widget.reparent(self.bottom_panel_dummy_hbox)
        self._window.get_bottom_panel().add_item(self.bottom_panel_dummy_hbox,"R Console",R_icon)
        self._window.get_bottom_panel().set_property("visible",True)
        self._window.get_bottom_panel().activate_item(self.bottom_panel_dummy_hbox)
        
    def on_R_Dialog_configure(self,widget,event):
        #self._plugin.prefs['RConsole_detached_x'] = event.x
        #self._plugin.prefs['RConsole_detached_y'] = event.y
        #self._plugin.prefs['RConsole_detached_width'] = event.width
        #self._plugin.prefs['RConsole_detached_height'] = event.height
        self._plugin.prefs['RConsole_detached_x'], self._plugin.prefs['RConsole_detached_y'] = self.Detached_R_Dialog.get_position()
        self._plugin.prefs['RConsole_detached_width'], self._plugin.prefs['RConsole_detached_height'] = self.Detached_R_Dialog.get_size()
        # Ugly hack due to the fact that for some reason I am not notified when gedit is closed...
        self._plugin.save_prefs()
        #print "R_Dialog_configure"
        
    def _remove_menu(self):
        # Get the GtkUIManager
        manager = self._window.get_ui_manager()

        # Remove the ui
        manager.remove_ui(self._ui_id)

        # Remove the action group
        manager.remove_action_group(self._action_group)

        # Make sure the manager updates
        manager.ensure_update()

    def update_ui(self):
        self._action_group.set_sensitive(self._window.get_active_document() != None)

    # Menu activate handlers
    def on_send_line_to_R(self, action):
        doc = self._window.get_active_document()
        if not doc:
            return
        view = self._window.get_active_view()
        if not view:
            return

        # The last line in the file:
        last_line = doc.get_end_iter().get_line()

        # If required so, try to send a non-empty and non-comment line,otherwise just the current line:
        while True:
            # Get the current line and send it:
            cur_line = doc.get_iter_at_mark(doc.get_insert()).get_line()
            start = doc.get_iter_at_line(cur_line)
            end=start.copy()
            end.forward_line()
            sel_text = doc.get_text(start,end)
            
            # Chek if the line is empty or a comment line:
            empty_or_comment = self._plugin.prefs['skip_empty_and_comment_lines'] and is_empty_comment_line(sel_text)
            if not empty_or_comment:
                if len(sel_text) == 0 or sel_text[-1] != '\n' and sel_text[-1] != '\r':
                    sel_text = sel_text + '\n'
                do_send_to_R( sel_text, self.R_widget, False ) # send always as source

            # and advance to the next line:
            if self._plugin.prefs['advance_to_next_line']:
                doc.goto_line(cur_line+1)
                view.scroll_mark_onscreen(doc.get_insert())
                
            if (not empty_or_comment) or (cur_line >= last_line):
                # That was it!
                break;
            

    def on_send_selection_to_R(self, action):
        doc = self._window.get_active_document()
        if not doc:
            return
        
        # See if anything is selected:
        if doc.get_has_selection():
            sel_bounds = doc.get_selection_bounds()
            sel_text = doc.get_text(sel_bounds[0],sel_bounds[1])
            if sel_text[-1] != '\n' and sel_text[-1] != '\r':
                sel_text = sel_text + '\n'
            do_send_to_R( sel_text, self.R_widget, False, self._plugin.prefs['max_lines_as_text'] )

    def on_send_file_to_R(self, action):
        doc = self._window.get_active_document()
        if not doc:
            return
        
        sel_text = doc.get_text(doc.get_start_iter(),doc.get_end_iter())
        do_send_to_R( sel_text, self.R_widget, True )

    def on_send_block1_to_R(self, action):
        doc = self._window.get_active_document()
        if not doc:
            return
        
        # Get the block positions (if any):
        try:
            block1_start = doc.get_iter_at_mark(doc.get_mark("RBlock1Start"))
            block1_end = doc.get_iter_at_mark(doc.get_mark("RBlock1End"))
            sel_text = doc.get_text(block1_start,block1_end)
            do_send_to_R( sel_text, self.R_widget, True )
        except:
            error_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Block 1 is not defined in the current document!" )
            error_dialog.run()
            error_dialog.destroy()
            return

    def on_define_block1(self, action):
        doc = self._window.get_active_document()
        if not doc:
            return
        
        # See if anything is selected:
        if not doc.get_has_selection():
            error_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "You need a selection in order to define a block!" )
            error_dialog.run()
            error_dialog.destroy()
            return

        # Prepare the view:
        view = self._window.get_active_view()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block1_start.png" , 24, 24)
        view.set_mark_category_pixbuf("RBlock1Start",pixbuf)
        try:
            view.set_mark_category_background("RBlock1Start",gtk.gdk.color_parse("lightblue"))
        except:
            pass
        view.set_mark_category_priority("RBlock1Start",100)
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block1_end.png" , 24, 24)
        view.set_mark_category_pixbuf("RBlock1End",pixbuf)
        try:
            view.set_mark_category_background("RBlock1End",gtk.gdk.color_parse("lightblue"))
        except:
            pass
        view.set_mark_category_priority("RBlock1End",100)
        view.set_show_line_marks(True)

        # Delete any previously existing:
        doc.remove_source_marks(doc.get_start_iter(),doc.get_end_iter(),"RBlock1Start")
        doc.remove_source_marks(doc.get_start_iter(),doc.get_end_iter(),"RBlock1End")
            
        # And create the new one here:
        sel_bounds = doc.get_selection_bounds()
        cur_line = sel_bounds[0].get_line()
        start = doc.get_iter_at_line(cur_line)
        block_start_mark = doc.create_source_mark("RBlock1Start","RBlock1Start",start)
        block_start_mark.set_visible(True)
        cur_line = sel_bounds[1].get_line()
        end = doc.get_iter_at_line(cur_line)
        end.forward_line()
        block_start_mark = doc.create_source_mark("RBlock1End","RBlock1End",end)
        block_start_mark.set_visible(True)

    def on_send_block2_to_R(self, action):
        doc = self._window.get_active_document()
        if not doc:
            return
        
        # Get the block positions (if any):
        try:
            block2_start = doc.get_iter_at_mark(doc.get_mark("RBlock2Start"))
            block2_end = doc.get_iter_at_mark(doc.get_mark("RBlock2End"))
            sel_text = doc.get_text(block2_start,block2_end)
            do_send_to_R( sel_text, self.R_widget, True )
        except:
            error_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Block 2 is not defined in the current document!" )
            error_dialog.run()
            error_dialog.destroy()
            return

    def on_define_block2(self, action):
        doc = self._window.get_active_document()
        if not doc:
            return
        
        # See if anything is selected:
        if not doc.get_has_selection():
            error_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "You need a selection in order to define a block!" )
            error_dialog.run()
            error_dialog.destroy()
            return

        # Prepare the view:
        view = self._window.get_active_view()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block2_start.png" , 24, 24)
        view.set_mark_category_pixbuf("RBlock2Start",pixbuf)
        try:
            view.set_mark_category_background("RBlock2Start",gtk.gdk.color_parse("gold"))
        except:
            pass
        view.set_mark_category_priority("RBlock2Start",100)
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.datadir+"/block2_end.png" , 24, 24)
        view.set_mark_category_pixbuf("RBlock2End",pixbuf)
        try:
            view.set_mark_category_background("RBlock2End",gtk.gdk.color_parse("gold"))
        except:
            pass
        view.set_mark_category_priority("RBlock2End",100)
        view.set_show_line_marks(True)

        # Delete any previously existing:
        doc.remove_source_marks(doc.get_start_iter(),doc.get_end_iter(),"RBlock2Start")
        doc.remove_source_marks(doc.get_start_iter(),doc.get_end_iter(),"RBlock2End")
            
        # And create the new one here:
        sel_bounds = doc.get_selection_bounds()
        cur_line = sel_bounds[0].get_line()
        start = doc.get_iter_at_line(cur_line)
        block_start_mark = doc.create_source_mark("RBlock2Start","RBlock2Start",start)
        block_start_mark.set_visible(True)
        cur_line = sel_bounds[1].get_line()
        end = doc.get_iter_at_line(cur_line)
        end.forward_line()
        block_start_mark = doc.create_source_mark("RBlock2End","RBlock2End",end)
        block_start_mark.set_visible(True)


    def on_R_config_dialog(self, action): 
        dialog = self._plugin.create_configure_dialog()
        dialog.run()

    def on_check_for_updates(self, action):
        # Get the current version:
        about_ui = gtk.glade.XML(self._plugin.get_data_dir()+"/About.glade")
        current_version = about_ui.get_widget('AboutDialog').get_version()
        # And the current version of the official wizards pack:
        wizards_pack_version_file = open( self._plugin.get_data_dir() + str("/Wizards/wizards.version"), "rt" )
        wizards_current_version = wizards_pack_version_file.read()
        wizards_current_version = wizards_current_version.strip()
        wizards_pack_version_file.close()
        
        # And the latest version available on the server:
        try:
            latest_version = urllib2.urlopen('http://rgedit.sourceforge.net/latest.version').read()
        except:
            error_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Cannot read the latest available version from rgedit's website!\nPlease, try again later..." )
            error_dialog.run()
            error_dialog.destroy()
            return
        try:
            wizards_latest_version = urllib2.urlopen('http://rgedit.sourceforge.net/wizards.latest.version').read()
        except:
            error_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Cannot read the latest available version of the wizards package from rgedit's website!\nPlease, try again later..." )
            error_dialog.run()
            error_dialog.destroy()
            return

        # Compare the two versions:
        if current_version.strip() == latest_version.strip() and wizards_current_version.strip() == wizards_latest_version.strip():
            question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "You have the latest version of rgedit (" + current_version.strip() + ") and official wizards package (" + wizards_current_version.strip() + ") installed." )
            response = question_dialog.run()
            question_dialog.destroy()
        elif current_version.strip() != latest_version.strip() and wizards_current_version.strip() != wizards_latest_version.strip():
            question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "You have version " + current_version.strip() + " of rgedit installed, but the newer " + latest_version.strip() + " is available, and version " + wizards_current_version.strip() + " of the official wizards package installed, but the newer " + wizards_latest_version.strip() + " is available.\n Would you like to download them?" )
            response = question_dialog.run()
            question_dialog.destroy()
            if response == gtk.RESPONSE_YES:
                webbrowser.open("http://rgedit.sourceforge.net/")
        elif current_version.strip() != latest_version.strip() and wizards_current_version.strip() == wizards_latest_version.strip():
            question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "You have version " + current_version.strip() + " of rgedit installed, but the newer " + latest_version.strip() + " is available.\n Would you like to download it?" )
            response = question_dialog.run()
            question_dialog.destroy()
            if response == gtk.RESPONSE_YES:
                webbrowser.open("http://rgedit.sourceforge.net/")
        else:
            question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "You have version " + wizards_current_version.strip() + " of the official wizards package installed, but the newer " + wizards_latest_version.strip() + " is available.\n Would you like to download it?" )
            response = question_dialog.run()
            question_dialog.destroy()
            if response == gtk.RESPONSE_YES:
                webbrowser.open("http://rgedit.sourceforge.net/")

    def on_create_new_R_tab(self, action):
        if self.R_widget == None:
            self.createRGeditTerminal()
        else:
            self.R_widget.create_new_R_tab()

    def on_R_search_selection_in_help(self,action):
        doc = self._window.get_active_document()
        if not doc:
            return
        
        # See if anything is selected:
        if doc.get_has_selection():
            sel_bounds = doc.get_selection_bounds()
            sel_text = doc.get_text(sel_bounds[0],sel_bounds[1])
            do_send_to_R( "? "+sel_text+"\n", self.R_widget, False, self._plugin.prefs['max_lines_as_text'] )

    def on_R_show_selection(self,action):
        doc = self._window.get_active_document()
        if not doc:
            return
        
        # See if anything is selected:
        if doc.get_has_selection():
            sel_bounds = doc.get_selection_bounds()
            sel_text = doc.get_text(sel_bounds[0],sel_bounds[1])
            do_send_to_R( "library(relimp); showData( "+sel_text+" )\n", self.R_widget, False, self._plugin.prefs['max_lines_as_text'] )

    def on_R_edit_selection(self,action):
        doc = self._window.get_active_document()
        if not doc:
            return
        
        # See if anything is selected:
        if doc.get_has_selection():
            sel_bounds = doc.get_selection_bounds()
            sel_text = doc.get_text(sel_bounds[0],sel_bounds[1])
            do_send_to_R( "fix( "+sel_text+" )\n", self.R_widget, False, self._plugin.prefs['max_lines_as_text'] )

    def on_R_help(self,action):
        webbrowser.open(self.datadir+"/Help/Help.html")

    def on_R_showhide(self,action):
        return
        
    def on_R_wizards(self,action):
        return

    def on_R_LandmarkComment(self,action):
        self._plugin.on_context_menu_landmark(None,self._window.get_active_document())
        return

    def on_R_about(self,action):
        about_ui = gtk.glade.XML(self.datadir+"/About.glade")
        about_dialog = about_ui.get_widget("AboutDialog")
        about_dialog.run()
        about_dialog.destroy()

    def on_R_load_workspace(self,action):
        self.R_widget.on_R_load_workspace()

    def on_R_save_workspace(self,action):
        self.R_widget.on_R_save_workspace()

    def on_toggle_ShowHideLine(self,checkmenuitem):
        manager = self._window.get_ui_manager()
        RCtrlLineToolitem = manager.get_widget("/ToolBar/RCtrlLine")
        if checkmenuitem.get_active():
            RCtrlLineToolitem.show()
        else:
            RCtrlLineToolitem.hide()
        self._plugin.prefs['show_run_line'] = checkmenuitem.get_active()
        self._plugin.save_prefs()

    def on_toggle_ShowHideSel(self,checkmenuitem):
        manager = self._window.get_ui_manager()
        RCtrlSelToolitem = manager.get_widget("/ToolBar/RCtrlSel")
        if checkmenuitem.get_active():
            RCtrlSelToolitem.show()
        else:
            RCtrlSelToolitem.hide()
        self._plugin.prefs['show_run_sel'] = checkmenuitem.get_active()
        self._plugin.save_prefs()

    def on_toggle_ShowHideAll(self,checkmenuitem):
        manager = self._window.get_ui_manager()
        RCtrlAllToolitem = manager.get_widget("/ToolBar/RCtrlAll")
        if checkmenuitem.get_active():
            RCtrlAllToolitem.show()
        else:
            RCtrlAllToolitem.hide()
        self._plugin.prefs['show_run_all'] = checkmenuitem.get_active()
        self._plugin.save_prefs()

    def on_toggle_ShowHideBlock1Run(self,checkmenuitem):
        manager = self._window.get_ui_manager()
        RCtrlBlock1RunToolitem = manager.get_widget("/ToolBar/RCtrlBlock1Run")
        if checkmenuitem.get_active():
            RCtrlBlock1RunToolitem.show()
        else:
            RCtrlBlock1RunToolitem.hide()
        self._plugin.prefs['show_run_block1'] = checkmenuitem.get_active()
        self._plugin.save_prefs()

    def on_toggle_ShowHideBlock1Def(self,checkmenuitem):
        manager = self._window.get_ui_manager()
        RCtrlBlock1DefToolitem = manager.get_widget("/ToolBar/RCtrlBlock1Def")
        if checkmenuitem.get_active():
            RCtrlBlock1DefToolitem.show()
        else:
            RCtrlBlock1DefToolitem.hide()
        self._plugin.prefs['show_def_block1'] = checkmenuitem.get_active()
        self._plugin.save_prefs()

    def on_toggle_ShowHideBlock2Run(self,checkmenuitem):
        manager = self._window.get_ui_manager()
        RCtrlBlock2RunToolitem = manager.get_widget("/ToolBar/RCtrlBlock2Run")
        if checkmenuitem.get_active():
            RCtrlBlock2RunToolitem.show()
        else:
            RCtrlBlock2RunToolitem.hide()
        self._plugin.prefs['show_run_block2'] = checkmenuitem.get_active()
        self._plugin.save_prefs()

    def on_toggle_ShowHideBlock2Def(self,checkmenuitem):
        manager = self._window.get_ui_manager()
        RCtrlBlock2DefToolitem = manager.get_widget("/ToolBar/RCtrlBlock2Def")
        if checkmenuitem.get_active():
            RCtrlBlock2DefToolitem.show()
        else:
            RCtrlBlock2DefToolitem.hide()
        self._plugin.prefs['show_def_block2'] = checkmenuitem.get_active()
        self._plugin.save_prefs()

    def on_toggle_ShowHideNewTab(self,checkmenuitem):
        manager = self._window.get_ui_manager()
        RCtrlNewTabToolitem = manager.get_widget("/ToolBar/RCtrlNewTab")
        if checkmenuitem.get_active():
            RCtrlNewTabToolitem.show()
        else:
            RCtrlNewTabToolitem.hide()
        self._plugin.prefs['show_new_tab'] = checkmenuitem.get_active()
        self._plugin.save_prefs()

    def on_R_attach(self,action):
        self.RConsole_attach = not self.RConsole_attach
        manager = self._window.get_ui_manager()
        AttachMenuItem = manager.get_widget("/MenuBar/R/RCtrlAttach")
        if self.RConsole_attach:
            AttachMenuItem.get_child().set_label('Attach R Console')
            if action != None:
                self.create_R_detached_dialog()
        else:
            AttachMenuItem.get_child().set_label('Detach R Console')
            if action != None:
                self.destroy_R_detached_dialog()

        #print "self.RConsole_attach is " + str(self.RConsole_attach)

    def on_R_close(self,action):
        question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "Are you sure you want to completely close the R console?\nAll open tabs will also be closed!" )
        response = question_dialog.run()
        question_dialog.destroy()

        if response == gtk.RESPONSE_YES:
            manager = self._window.get_ui_manager()
            # Make them insensitive and invisible, depending on the action:
            manager.get_action("/ToolBar/RCtrlLine").set_sensitive(False)
            manager.get_action("/ToolBar/RCtrlSel").set_sensitive(False)
            manager.get_action("/ToolBar/RCtrlAll").set_sensitive(False)
            manager.get_action("/ToolBar/RCtrlNewTab").set_sensitive(True)
            #manager.get_action("/ToolBar/RCtrlConfig").set_sensitive(True)
            manager.get_action("/MenuBar/R/RCtrlBlock1Run").set_sensitive(False)
            manager.get_action("/MenuBar/R/RCtrlBlock2Run").set_sensitive(False)
            #manager.get_action("/MenuBar/R/RCtrlLoadWorkspace").set_sensitive(False)
            #manager.get_action("/MenuBar/R/RCtrlSaveWorkspace").set_sensitive(False)
            #manager.get_action("/MenuBar/R/RCtrlHelpSel").set_sensitive(False)
            #manager.get_action("/MenuBar/R/RCtrlShowSel").set_sensitive(False)
            #manager.get_action("/MenuBar/R/RCtrlEditSel").set_sensitive(False)
            manager.get_action("/MenuBar/R/RCtrlAttach").set_sensitive(False)
            manager.get_action("/MenuBar/R/RCtrlClose").set_sensitive(False)
            
            # Close it!
            if self.R_widget._vte != None:
                self.R_widget.kill_shell_process(self.R_widget._vte1_shell_PID)
                self.R_widget._vte1_shell_PID = -1
                #self.R_widget._vte.feed_child("q()\n")
                #self.R_widget._vte.feed_child("exit\n")
            if self.R_widget._vte2 != None:
                self.R_widget.kill_shell_process(self.R_widget._vte2_shell_PID)
                self.R_widget._vte2_shell_PID = -1
                #self.R_widget._vte2.feed_child("q()\n")
                #self.R_widget._vte2.feed_child("exit\n")
            if self.R_widget._vte3 != None:
                self.R_widget.kill_shell_process(self.R_widget._vte3_shell_PID)
                self.R_widget._vte3_shell_PID = -1
                #self.R_widget._vte3.feed_child("q()\n")
                #self.R_widget._vte3.feed_child("exit\n")
            ## Give them time to exit
            #time.sleep(1)
            self.R_widget.destroy()
            self.R_widget = None
            if self.RConsole_attach and self.Detached_R_Dialog != None:
                self.Detached_R_Dialog.destroy()
                self.Detached_R_Dialog = None
            if not self.RConsole_attach and self.bottom_panel_dummy_hbox != None:
                self._window.get_bottom_panel().remove_item(self.bottom_panel_dummy_hbox)
        

    def update_R_consoles(self,vte1_console_changed,vte2_console_changed,vte3_console_changed,vte1_R_options_changed,vte2_R_options_changed,vte3_R_options_changed):
        # Update the R consoles because some options have changed
        if self.R_widget != None:
            self.R_widget.reconfigure_vtes(vte1_console_changed,vte2_console_changed,vte3_console_changed,vte1_R_options_changed,vte2_R_options_changed,vte3_R_options_changed)


class RCtrlPlugin(gedit.Plugin):

    # The plugin preferences:
    prefs = {
        'autostart_R_console'   : True,   # should the R console in the panel start automatically?
        'max_lines_as_text'     : 20,   # the number of lines to send selection as text
        'echo_commands'         : True, # should commands sent to R through source() be echoed in the R console?
        'HTML_help'             : True, # use HTML help?
        'advance_to_next_line'  : True, # advance to next line after sending current line to R?
        'allow_bold'            : True,
        'audible_bell'          : False,
        'background1'            : "white",
        'foreground1'            : "black",
        'prompt_color1'          : None,
        'background2'            : "white",
        'foreground2'            : "black",
        'prompt_color2'          : None,
        'background3'            : "white",
        'foreground3'            : "black",
        'prompt_color3'          : None,
        'tab_name_in_prompt'    : True,
        'backspace_binding'     : 'ascii-del',
        'cursor_blink'          : 'system',  # system, on, off
        'cursor_shape'          : 'block',   # block, ibeam, underline
        'emulation'             : 'xterm',
        'font_name'             : 'Monospace 8',
        'scroll_on_keystroke'   : True,
        'scroll_on_output'      : True,
        'scrollback_lines'      : 5000,
        'visible_bell'          : False,
        'word_chars'            : '-A-Za-z0-9,./?%&#:_',
        'show_run_line'         : True,
        'show_run_sel'          : True,
        'show_run_all'          : True,
        'show_run_block1'       : True,
        'show_def_block1'       : True,
        'show_run_block2'       : True,
        'show_def_block2'       : True,
        'show_new_tab'          : True,
        'shortcut_RCtrlLine'    : '<Ctrl><Shift>R', # user-definible keyboard shortcuts
        'shortcut_RCtrlSel'     : '<Ctrl><Shift>E',
        'shortcut_RCtrlAll'     : None,
        'shortcut_RCtrlBlock1Run' : '<Ctrl><Shift>F1',
        'shortcut_RCtrlBlock1Def' : None,
        'shortcut_RCtrlBlock2Run' : '<Ctrl><Shift>F2',
        'shortcut_RCtrlBlock2Def' : None,
        'shortcut_RCtrlNewTab'  : None,
        'shortcut_RCtrlConfig'  : None,
        'shortcut_RCtrlLoadWorkspace' : None,
        'shortcut_RCtrlSaveWorkspace' : None,
        #'shortcut_RCtrlHelpSel' : '<Ctrl><Shift>H',
        #'shortcut_RCtrlShowSel' : None,
        #'shortcut_RCtrlEditSel' : None,
        'shortcut_RCtrlAttach'  : None,
        'shortcut_RCtrlClose'   : None,
        'RConsole_start_attached' : False,
        'RConsole_detached_x'      : -1,
        'RConsole_detached_y'      : -1,
        'RConsole_detached_width'  : -1,
        'RConsole_detached_height' : -1,
        'skip_empty_and_comment_lines' : True,
        'autostart_R_script'      : False,
        'autostart_R_script_path' : None,
        'R_structure_enabled' : True,
        'R_structure_landmarks' : True,
        'R_structure_functions' : True,
        'R_structure_dataframes' : True,
        'use_current_document_directory' : True,
        'R_console_tab_pos' : gtk.POS_RIGHT,
        'R_console_always_show_tabs' : False,
        'R_console_Ctrl_C_4_copy' : True,
        'R_console_Ctrl_Q_break' : True,
        'R_console_Escape_break' : True,
        'show_messages_and_warnings' : True
    }

    def __init__(self):
        self.id_name = 'RCtrlPlugin'
        gedit.Plugin.__init__(self)
        self._instances = {}

        # Load the saved preferences:
        try:
            pref_file = open(os.path.expanduser("~/.rgedit-preferences"),"r")
            saved_prefs = pickle.load(pref_file)
            for i in list(self.prefs.keys()):
                if i in saved_prefs:
                    self.prefs[i] = saved_prefs[i]
            close(pref_file)
        except:
            pass
            
        # Checks:
        if self.prefs['autostart_R_script_path'] == None:
            self.prefs['autostart_R_script'] = False
            
        # There are some special shortcuts of potential interest, esp. modifiers of ENTER:
        self.check_special_shortcuts()
            
        # Context menu stuff:
        self.window = None
        
    def check_special_shortcuts(self):
        # There are some special shortcuts of potential interest, esp. modifiers of ENTER,
        # for runing the current line, block, all files, etc...
        self.special_shortcut_RCtrlLine      = [None,None]
        self.special_shortcut_RCtrlSel       = [None,None]
        self.special_shortcut_RCtrlAll       = [None,None]
        self.special_shortcut_RCtrlBlock1Run = [None,None]
        self.special_shortcut_RCtrlBlock2Run = [None,None]
            
        # Set the possible modifiers (Control Shift and Alt):
        self.possible_modifiers = (gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK | gtk.gdk.MOD1_MASK)
        
        key, modifier = gtk.accelerator_parse(str(self.prefs['shortcut_RCtrlLine']))
        if key != 0 and gtk.gdk.keyval_name(key).lower() == "return":
            self.special_shortcut_RCtrlLine = ["return",modifier]
            
        key, modifier = gtk.accelerator_parse(str(self.prefs['shortcut_RCtrlSel']))
        if key != 0 and gtk.gdk.keyval_name(key).lower() == "return":
            self.special_shortcut_RCtrlSel = ["return",modifier]
            
        key, modifier = gtk.accelerator_parse(str(self.prefs['shortcut_RCtrlAll']))
        if key != 0 and gtk.gdk.keyval_name(key).lower() == "return":
            self.special_shortcut_RCtrlAll = ["return",modifier]
            
        key, modifier = gtk.accelerator_parse(str(self.prefs['shortcut_RCtrlBlock1Run']))
        if key != 0 and gtk.gdk.keyval_name(key).lower() == "return":
            self.special_shortcut_RCtrlBlock1Run = ["return",modifier]
            
        key, modifier = gtk.accelerator_parse(self.prefs['shortcut_RCtrlBlock2Run'])
        if gtk.gdk.keyval_name(key).lower() == "return":
            self.special_shortcut_RCtrlBlock2Run = ["return",modifier]
        
    def get_data_dir(self):
        try:
            return gedit.Plugin.get_data_dir(self)
        except:
            return self.get_data_directory()

    def get_data_directory(self):
        if platform.platform() == 'Windows':
            return os.path.expanduser('~/gedit/plugins/RCtrl')
        else:
            return os.path.expanduser('~/.gnome2/gedit/plugins/RCtrl')

    def activate(self, window):
        self._instances[window] = RCtrlWindowHelper(self, window)
        
        # Context menu handling stuff:
        self.window = window

        handler_ids = []
        for signal in ('tab-added', 'tab-removed', 'active-tab-changed'):
            method = getattr(self, 'on_window_' + signal.replace('-', '_'))
            handler_ids.append(window.connect(signal, method))
        window.set_data(self.id_name, handler_ids)

        for view in window.get_views():
            self.connect_view(view,self._instances[window])

        for doc in window.get_documents():
            self.connect_document(doc,window)
            
    def deactivate(self, window):
        # Context menu stuff:
        widgets = [window] + window.get_views()
        for widget in widgets:
            handler_ids = widget.get_data(self.id_name)
            if not handler_ids is None:
                for handler_id in handler_ids:
                    widget.disconnect(handler_id)
            widget.set_data(self.id_name, None)

        for doc in window.get_documents():
            handler_id = doc.get_data(self.id_name)
            doc.disconnect(handler_id)
            doc.set_data(self.id_name, None)

        self.window = None
		
        # Save the options to file first:
        self.save_prefs()
        # Deativate the plugin instance:
        self._instances[window].deactivate()
        del self._instances[window]

    def connect_view(self, view, rctrlwindowhelper):
        handler_id = view.connect('populate-popup', self.on_view_populate_popup, rctrlwindowhelper)
        view.set_data(self.id_name, [handler_id])
        
        # Key press dispatcher for processing the shortcuts:
        handler_id = view.connect('key_press_event', self.on_view_key_press_event, rctrlwindowhelper)
        
    def on_view_key_press_event(self, widget, event, rctrlwindowhelper):
        # Process the special shortcuts (if any) before gedit has any chance:
        event_key = gtk.gdk.keyval_name(event.keyval).lower()
        if event_key != "return":
            return False
            
        event_modifiers = (event.state & self.possible_modifiers)

        if (self.special_shortcut_RCtrlLine[0] == event_key) and (event_modifiers == self.special_shortcut_RCtrlLine[1]):
            rctrlwindowhelper.on_send_line_to_R(None)
            return True

        if (self.special_shortcut_RCtrlSel[0] == event_key) and (event_modifiers == self.special_shortcut_RCtrlSel[1]):
            rctrlwindowhelper.on_send_selection_to_R(None)
            return True

        if (self.special_shortcut_RCtrlAll[0] == event_key) and (event_modifiers == self.special_shortcut_RCtrlAll[1]):
            rctrlwindowhelper.on_send_file_to_R_(None)
            return True

        if (self.special_shortcut_RCtrlBlock1Run[0] == event_key) and (event_modifiers == self.special_shortcut_RCtrlBlock1Run[1]):
            rctrlwindowhelper.on_send_block1_to_R(None)
            return True

        if (self.special_shortcut_RCtrlBlock2Run[0] == event_key) and (event_modifiers == self.special_shortcut_RCtrlBlock2Run[1]):
            rctrlwindowhelper.on_send_block2_to_R(None)
            return True

        return False

    def connect_document(self, doc, window):
        handler_id = doc.connect("saved", self.on_document_saved, window)
        handler_id = doc.connect("loaded", self.on_document_loaded, window)
        doc.set_data(self.id_name, [handler_id])

    def update_ui(self, window):
        self._instances[window].update_ui()

    def is_configurable(self):
        return True

    def on_window_tab_added(self, window, tab):
        self.connect_view(tab.get_view(),self._instances[window])
        
        doc = tab.get_document()
        handler_id = doc.get_data(self.id_name)
        if handler_id is None:
            self.connect_document(doc,window)

    def on_window_active_tab_changed(self, window, tab):
        self._instances[window]._rstructurepanel.on_force_refresh(None)
        
    def on_window_tab_removed(self, window, tab):
        pass

    def on_document_saved(self, doc, ignore1, window):
        self._instances[window]._rstructurepanel.on_force_refresh(None)

    def on_document_loaded(self, doc, ignore1, window):
        self._instances[window]._rstructurepanel.on_force_refresh(None)

    def on_view_populate_popup(self, view, menu, rctrlwindowhelper):
        doc = view.get_buffer()

        # The Wizards context menu:
        wizardmenu = gtk.ImageMenuItem(_("Wizards"))
        #wizardmenu.set_image(gtk.image_new_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_MENU))
        wizardmenu.connect('activate', self.on_context_menu_wizard);
        wizardmenu.show();
        
        rctrlwindowhelper.fill_in_wizards_menu( wizardmenu )
        landmarkmenu = gtk.ImageMenuItem(_("Insert Landmark Comment"))
        menu_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.get_data_dir()+"/landmark_comment.png",16,16)
        menu_icon.set_from_pixbuf(pixbuf)
        menu_icon.show()
        landmarkmenu.set_image(menu_icon)
        landmarkmenu.connect('activate', self.on_context_menu_landmark, doc);
        landmarkmenu.show();
        # The Landmark Comment menu entry:

        separator = gtk.SeparatorMenuItem()
        separator.show();

        menu.prepend(separator)
        menu.prepend(wizardmenu)
        menu.prepend(landmarkmenu)
        return True
	
    def on_context_menu_wizard(self, menu_item):
        #print "Wirzad from context menu!"
        return True

    def on_context_menu_landmark(self, menu_item, doc):
        # Insert the landmark special comment at the beginning of the next line:
        if doc == None:
            # Nothing to do!
            return True
        # Get the cursor's location:
        cursor_iter = doc.get_iter_at_mark(doc.get_insert())
        # and go to the end of the line:
        if not cursor_iter.ends_line():
            cursor_iter.forward_to_line_end()
        # then insert a newline and the comment text:
        doc.insert(cursor_iter,str("\n")+landmark_comment_header+landmark_comment_placeholder)
        return True

    def create_configure_dialog(self):
        self.ui = gtk.glade.XML(self.get_data_dir()+"/ConfigDialog.glade")

        # Init the controls accordingly with the current options:
        check_box_autostart_R = self.ui.get_widget("AutostartR")
        check_box_autostart_R.set_active(self.prefs['autostart_R_console'])

        check_box_use_doc_dir = self.ui.get_widget("UseDocDirectory")
        check_box_use_doc_dir.set_active(self.prefs['use_current_document_directory'])

        check_box_show_message = self.ui.get_widget("ShowMessageCheck")
        check_box_show_message.set_active(self.prefs['show_messages_and_warnings'])

        check_box_attached_R = self.ui.get_widget("StartRAttached")
        check_box_attached_R.set_active(self.prefs['RConsole_start_attached'])

        check_box_autostart_script = self.ui.get_widget("AutostartScriptCheck")
        check_box_autostart_script.set_active(self.prefs['autostart_R_script'])

        if self.prefs['autostart_R_script_path'] != None:
            file_chooser_autostart_script = self.ui.get_widget("AutorunScriptPath")
            file_chooser_autostart_script.set_filename(self.prefs['autostart_R_script_path'])

        spin_max_lines_as_text = self.ui.get_widget("MaxLinesToSendSpin")
        spin_max_lines_as_text.set_value(self.prefs['max_lines_as_text'])

        check_box_HTML_help = self.ui.get_widget("HTMLHelpCheck")
        check_box_HTML_help.set_active(self.prefs['HTML_help'])
        
        check_box_echo_commands = self.ui.get_widget("EchoPipedCommandsCheck")
        check_box_echo_commands.set_active(self.prefs['echo_commands'])
        
        check_box_advance_line = self.ui.get_widget("AdvanceLineCheck")
        check_box_advance_line.set_active(self.prefs['advance_to_next_line'])

        check_box_skip_empty_and_comment = self.ui.get_widget("SkipEmptyAndCommentCheck")
        check_box_skip_empty_and_comment.set_active(self.prefs['skip_empty_and_comment_lines'])

        check_box_audible_bell = self.ui.get_widget("AudibleBell")
        check_box_audible_bell.set_active(self.prefs['audible_bell'])
        
        check_box_visible_bell = self.ui.get_widget("VisibleBell")
        check_box_visible_bell.set_active(self.prefs['visible_bell'])
        
        check_box_scroll_on_keystroke = self.ui.get_widget("ScrollOnKeystroke")
        check_box_scroll_on_keystroke.set_active(self.prefs['scroll_on_keystroke'])
        
        check_box_scroll_on_output = self.ui.get_widget("ScrollOnOutput")
        check_box_scroll_on_output.set_active(self.prefs['scroll_on_output'])
        
        edit_scrollback_lines = self.ui.get_widget("ScrollbackLines")
        edit_scrollback_lines.set_text(str(self.prefs['scrollback_lines']))

        if self.prefs['cursor_blink'] == "system":
            radio_button_cursor_blink = self.ui.get_widget("BlinkSystem")
            radio_button_cursor_blink.set_active(True)
        elif self.prefs['cursor_blink'] == "on":
            radio_button_cursor_blink = self.ui.get_widget("BlinkOn")
            radio_button_cursor_blink.set_active(True)
        elif self.prefs['cursor_blink'] == "off":
            radio_button_cursor_blink = self.ui.get_widget("BlinkOff")
            radio_button_cursor_blink.set_active(True)

        if self.prefs['cursor_shape'] == "block":
            radio_button_cursor_shape = self.ui.get_widget("ShapeBlock")
            radio_button_cursor_shape.set_active(True)
        elif self.prefs['cursor_shape'] == "ibeam":
            radio_button_cursor_shape = self.ui.get_widget("ShapeIBeam")
            radio_button_cursor_shape.set_active(True)
        elif self.prefs['cursor_shape'] == "underline":
            radio_button_cursor_shape = self.ui.get_widget("ShapeUnderline")
            radio_button_cursor_shape.set_active(True)

        color_button_foreground1 = self.ui.get_widget("ForegroundColor1")
        color_button_foreground1.set_color(gtk.gdk.color_parse(self.prefs['foreground1']))

        color_button_background1 = self.ui.get_widget("BackgroundColor1")
        color_button_background1.set_color(gtk.gdk.color_parse(self.prefs['background1']))

        combo_box_prompt_color1 = self.ui.get_widget("PromptColor1")
        combo_box_prompt_color1.set_active(self.xterm_color_to_index(self.prefs['prompt_color1']))
        
        color_button_foreground2 = self.ui.get_widget("ForegroundColor2")
        color_button_foreground2.set_color(gtk.gdk.color_parse(self.prefs['foreground2']))

        color_button_background2 = self.ui.get_widget("BackgroundColor2")
        color_button_background2.set_color(gtk.gdk.color_parse(self.prefs['background2']))

        combo_box_prompt_color2 = self.ui.get_widget("PromptColor2")
        combo_box_prompt_color2.set_active(self.xterm_color_to_index(self.prefs['prompt_color2']))
        
        color_button_foreground3 = self.ui.get_widget("ForegroundColor3")
        color_button_foreground3.set_color(gtk.gdk.color_parse(self.prefs['foreground3']))

        color_button_background3 = self.ui.get_widget("BackgroundColor3")
        color_button_background3.set_color(gtk.gdk.color_parse(self.prefs['background3']))

        combo_box_prompt_color3 = self.ui.get_widget("PromptColor3")
        combo_box_prompt_color3.set_active(self.xterm_color_to_index(self.prefs['prompt_color3']))
        
        check_box_tab_name_in_prompt = self.ui.get_widget("TabNameInPrompt")
        check_box_tab_name_in_prompt.set_active(self.prefs['tab_name_in_prompt'])
        
        font_button = self.ui.get_widget("CurrentFont")
        font_button.set_font_name( self.prefs['font_name'] )

        self.dialog = self.ui.get_widget("RConfigDialog")

        #Create our dictionay and connect it
        dic = { "on_ButtonOk_clicked" : self.ButtonOk_clicked,
                "on_ButtonCancel_clicked" : self.ButtonCancel_clicked,
                "on_ChangeShortcuts_clicked" : self.ButtonChangeShortcuts_clicked,
                "on_SidePanelOptions_clicked" : self.ButtonSidePanelOptions_clicked,
                "on_MainWindow_destroy" : gtk.main_quit }
        self.ui.signal_autoconnect(dic)

        return self.dialog

    def ButtonChangeShortcuts_clicked(self,widget):
        ChangeShortcuts_ui = gtk.glade.XML(self.get_data_dir()+"/ShortcutsDialog.glade")

        edit_RCtrlLine_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlLine_Shortcut")
        edit_RCtrlLine_Shortcut.set_text(str(self.prefs['shortcut_RCtrlLine']))

        edit_RCtrlSel_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlSel_Shortcut")
        edit_RCtrlSel_Shortcut.set_text(str(self.prefs['shortcut_RCtrlSel']))

        edit_RCtrlAll_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlAll_Shortcut")
        edit_RCtrlAll_Shortcut.set_text(str(self.prefs['shortcut_RCtrlAll']))

        edit_RCtrlBlock1Run_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlBlock1Run_Shortcut")
        edit_RCtrlBlock1Run_Shortcut.set_text(str(self.prefs['shortcut_RCtrlBlock1Run']))

        edit_RCtrlBlock1Def_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlBlock1Def_Shortcut")
        edit_RCtrlBlock1Def_Shortcut.set_text(str(self.prefs['shortcut_RCtrlBlock1Def']))

        edit_RCtrlBlock2Run_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlBlock2Run_Shortcut")
        edit_RCtrlBlock2Run_Shortcut.set_text(str(self.prefs['shortcut_RCtrlBlock2Run']))

        edit_RCtrlBlock2Def_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlBlock2Def_Shortcut")
        edit_RCtrlBlock2Def_Shortcut.set_text(str(self.prefs['shortcut_RCtrlBlock2Def']))

        edit_RCtrlNewTab_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlNewTab_Shortcut")
        edit_RCtrlNewTab_Shortcut.set_text(str(self.prefs['shortcut_RCtrlNewTab']))

        edit_RCtrlConfig_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlConfig_Shortcut")
        edit_RCtrlConfig_Shortcut.set_text(str(self.prefs['shortcut_RCtrlConfig']))

        edit_RCtrlLoadWorkspace_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlLoadWorkspace_Shortcut")
        edit_RCtrlLoadWorkspace_Shortcut.set_text(str(self.prefs['shortcut_RCtrlLoadWorkspace']))

        edit_RCtrlSaveWorkspace_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlSaveWorkspace_Shortcut")
        edit_RCtrlSaveWorkspace_Shortcut.set_text(str(self.prefs['shortcut_RCtrlSaveWorkspace']))

        #edit_RCtrlHelpSel_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlHelpSel_Shortcut")
        #edit_RCtrlHelpSel_Shortcut.set_text(str(self.prefs['shortcut_RCtrlHelpSel']))
        #
        #edit_RCtrlShowSel_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlShowSel_Shortcut")
        #edit_RCtrlShowSel_Shortcut.set_text(str(self.prefs['shortcut_RCtrlShowSel']))
        #
        #edit_RCtrlEditSel_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlEditSel_Shortcut")
        #edit_RCtrlEditSel_Shortcut.set_text(str(self.prefs['shortcut_RCtrlEditSel']))

        edit_RCtrlAttach_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlAttach_Shortcut")
        edit_RCtrlAttach_Shortcut.set_text(str(self.prefs['shortcut_RCtrlAttach']))

        edit_RCtrlClose_Shortcut = ChangeShortcuts_ui.get_widget("RCtrlClose_Shortcut")
        edit_RCtrlClose_Shortcut.set_text(str(self.prefs['shortcut_RCtrlClose']))

        check_CtrlC_4_Copy = ChangeShortcuts_ui.get_widget("CtrlC_4_Copy")
        check_CtrlC_4_Copy.set_active(self.prefs['R_console_Ctrl_C_4_copy'])

        check_CtrlQ_break = ChangeShortcuts_ui.get_widget("CtrlQ_break")
        check_CtrlQ_break.set_active(self.prefs['R_console_Ctrl_Q_break'])

        check_Escape_break = ChangeShortcuts_ui.get_widget("Escape_break")
        check_Escape_break.set_active(self.prefs['R_console_Escape_break'])

        ChangeShortcuts_dialog = ChangeShortcuts_ui.get_widget("EditKeyboardShortcuts")

        malformed_data = True
        while malformed_data == True:
            malformed_data = False
            response = ChangeShortcuts_dialog.run()

            if response == -2: #OK button
                # Collect the data:
                shortcut_RCtrlLine = ChangeShortcuts_ui.get_widget("RCtrlLine_Shortcut").get_text()
                shortcut_RCtrlSel = ChangeShortcuts_ui.get_widget("RCtrlSel_Shortcut").get_text()
                shortcut_RCtrlAll = ChangeShortcuts_ui.get_widget("RCtrlAll_Shortcut").get_text()
                shortcut_RCtrlBlock1Run = ChangeShortcuts_ui.get_widget("RCtrlBlock1Run_Shortcut").get_text()
                shortcut_RCtrlBlock1Def = ChangeShortcuts_ui.get_widget("RCtrlBlock1Def_Shortcut").get_text()
                shortcut_RCtrlBlock2Run = ChangeShortcuts_ui.get_widget("RCtrlBlock2Run_Shortcut").get_text()
                shortcut_RCtrlBlock2Def = ChangeShortcuts_ui.get_widget("RCtrlBlock2Def_Shortcut").get_text()
                shortcut_RCtrlNewTab = ChangeShortcuts_ui.get_widget("RCtrlNewTab_Shortcut").get_text()
                shortcut_RCtrlConfig = ChangeShortcuts_ui.get_widget("RCtrlConfig_Shortcut").get_text()
                shortcut_RCtrlLoadWorkspace = ChangeShortcuts_ui.get_widget("RCtrlLoadWorkspace_Shortcut").get_text()
                shortcut_RCtrlSaveWorkspace = ChangeShortcuts_ui.get_widget("RCtrlSaveWorkspace_Shortcut").get_text()
                #shortcut_RCtrlHelpSel = ChangeShortcuts_ui.get_widget("RCtrlHelpSel_Shortcut").get_text()
                #shortcut_RCtrlShowSel = ChangeShortcuts_ui.get_widget("RCtrlShowSel_Shortcut").get_text()
                #shortcut_RCtrlEditSel = ChangeShortcuts_ui.get_widget("RCtrlEditSel_Shortcut").get_text()
                shortcut_RCtrlAttach = ChangeShortcuts_ui.get_widget("RCtrlAttach_Shortcut").get_text()
                shortcut_RCtrlClose = ChangeShortcuts_ui.get_widget("RCtrlClose_Shortcut").get_text()
                check_CtrlC_4_Copy = ChangeShortcuts_ui.get_widget("CtrlC_4_Copy").get_active()
                check_CtrlQ_break = ChangeShortcuts_ui.get_widget("CtrlQ_break").get_active()
                check_Escape_break = ChangeShortcuts_ui.get_widget("Escape_break").get_active()

                # Check the data:
                if shortcut_RCtrlLine == 'None':
                    shortcut_RCtrlLine = None
                elif gtk.accelerator_parse(shortcut_RCtrlLine) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Run current line' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlLine_Shortcut").grab_focus()

                if shortcut_RCtrlSel == 'None':
                    shortcut_RCtrlSel = None
                elif gtk.accelerator_parse(shortcut_RCtrlSel) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Run selection' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlSel_Shortcut").grab_focus()

                if shortcut_RCtrlAll == 'None':
                    shortcut_RCtrlAll = None
                elif gtk.accelerator_parse(shortcut_RCtrlAll) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Run whole file' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlAll_Shortcut").grab_focus()

                if shortcut_RCtrlBlock1Run == 'None':
                    shortcut_RCtrlBlock1Run = None
                elif gtk.accelerator_parse(shortcut_RCtrlBlock1Run) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Run block 1' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlBlock1Run_Shortcut").grab_focus()

                if shortcut_RCtrlBlock1Def == 'None':
                    shortcut_RCtrlBlock1Def = None
                elif gtk.accelerator_parse(shortcut_RCtrlBlock1Def) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Define block 1' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlBlock1Def_Shortcut").grab_focus()

                if shortcut_RCtrlBlock2Run == 'None':
                    shortcut_RCtrlBlock2Run = None
                elif gtk.accelerator_parse(shortcut_RCtrlBlock2Run) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Run block 2' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlBlock2Run_Shortcut").grab_focus()

                if shortcut_RCtrlBlock2Def == 'None':
                    shortcut_RCtrlBlock2Def = None
                elif gtk.accelerator_parse(shortcut_RCtrlBlock2Def) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Define block 2' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlBlock2Def_Shortcut").grab_focus()

                if shortcut_RCtrlNewTab == 'None':
                    shortcut_RCtrlNewTab = None
                elif gtk.accelerator_parse(shortcut_RCtrlNewTab) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Create new R tab' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlNewTab_Shortcut").grab_focus()

                if shortcut_RCtrlConfig == 'None':
                    shortcut_RCtrlConfig = None
                elif gtk.accelerator_parse(shortcut_RCtrlConfig) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Configure R interface' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlConfig_Shortcut").grab_focus()

                if shortcut_RCtrlLoadWorkspace == 'None':
                    shortcut_RCtrlLoadWorkspace = None
                elif gtk.accelerator_parse(shortcut_RCtrlLoadWorkspace) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Load R Workspace' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlLoadWorkspace_Shortcut").grab_focus()

                if shortcut_RCtrlSaveWorkspace == 'None':
                    shortcut_RCtrlSaveWorkspace = None
                elif gtk.accelerator_parse(shortcut_RCtrlSaveWorkspace) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Save R Workspace' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlSaveWorkspace_Shortcut").grab_focus()

                #if shortcut_RCtrlHelpSel == 'None':
                #    shortcut_RCtrlHelpSel = None
                #elif gtk.accelerator_parse(shortcut_RCtrlHelpSel) == (0,0):
                #    malformed_data = True
                #    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Search sel in help' is malformed!" )
                #    shortcut_dialog.run()
                #    shortcut_dialog.destroy()
                #    ChangeShortcuts_ui.get_widget("RCtrlHelpSel_Shortcut").grab_focus()
                #
                #if shortcut_RCtrlShowSel == 'None':
                #    shortcut_RCtrlShowSel = None
                #elif gtk.accelerator_parse(shortcut_RCtrlShowSel) == (0,0):
                #    malformed_data = True
                #    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'showData(selection)' is malformed!" )
                #    shortcut_dialog.run()
                #    shortcut_dialog.destroy()
                #    ChangeShortcuts_ui.get_widget("RCtrlShowSel_Shortcut").grab_focus()
                #
                #if shortcut_RCtrlEditSel == 'None':
                #    shortcut_RCtrlEditSel = None
                #elif gtk.accelerator_parse(shortcut_RCtrlEditSel) == (0,0):
                #    malformed_data = True
                #    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'fix(selection)' is malformed!" )
                #    shortcut_dialog.run()
                #    shortcut_dialog.destroy()
                #    ChangeShortcuts_ui.get_widget("RCtrlEditSel_Shortcut").grab_focus()

                if shortcut_RCtrlAttach == 'None':
                    shortcut_RCtrlAttach = None
                elif gtk.accelerator_parse(shortcut_RCtrlAttach) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Attach/detach R console' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlAttach_Shortcut").grab_focus()

                if shortcut_RCtrlClose == 'None':
                    shortcut_RCtrlClose = None
                elif gtk.accelerator_parse(shortcut_RCtrlClose) == (0,0):
                    malformed_data = True
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Key shortcut for 'Close R console' is malformed!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()
                    ChangeShortcuts_ui.get_widget("RCtrlClose_Shortcut").grab_focus()

                # See if the data has changed:
                #if shortcut_RCtrlLine != self.prefs['shortcut_RCtrlLine'] or shortcut_RCtrlSel != self.prefs['shortcut_RCtrlSel'] or shortcut_RCtrlAll != self.prefs['shortcut_RCtrlAll'] or shortcut_RCtrlBlock1Run != self.prefs['shortcut_RCtrlBlock1Run'] or shortcut_RCtrlBlock1Def != self.prefs['shortcut_RCtrlBlock1Def'] or shortcut_RCtrlBlock2Run != self.prefs['shortcut_RCtrlBlock2Run'] or shortcut_RCtrlBlock2Def != self.prefs['shortcut_RCtrlBlock2Def'] or shortcut_RCtrlNewTab != self.prefs['shortcut_RCtrlNewTab'] or shortcut_RCtrlConfig != self.prefs['shortcut_RCtrlConfig'] or shortcut_RCtrlLoadWorkspace != self.prefs['shortcut_RCtrlLoadWorkspace'] or shortcut_RCtrlSaveWorkspace != self.prefs['shortcut_RCtrlSaveWorkspace'] or shortcut_RCtrlHelpSel != self.prefs['shortcut_RCtrlHelpSel'] or shortcut_RCtrlShowSel != self.prefs['shortcut_RCtrlShowSel'] or shortcut_RCtrlEditSel != self.prefs['shortcut_RCtrlEditSel'] or shortcut_RCtrlAttach != self.prefs['shortcut_RCtrlAttach'] or shortcut_RCtrlClose != self.prefs['shortcut_RCtrlClose']:
                if shortcut_RCtrlLine != self.prefs['shortcut_RCtrlLine'] or shortcut_RCtrlSel != self.prefs['shortcut_RCtrlSel'] or shortcut_RCtrlAll != self.prefs['shortcut_RCtrlAll'] or shortcut_RCtrlBlock1Run != self.prefs['shortcut_RCtrlBlock1Run'] or shortcut_RCtrlBlock1Def != self.prefs['shortcut_RCtrlBlock1Def'] or shortcut_RCtrlBlock2Run != self.prefs['shortcut_RCtrlBlock2Run'] or shortcut_RCtrlBlock2Def != self.prefs['shortcut_RCtrlBlock2Def'] or shortcut_RCtrlNewTab != self.prefs['shortcut_RCtrlNewTab'] or shortcut_RCtrlConfig != self.prefs['shortcut_RCtrlConfig'] or shortcut_RCtrlLoadWorkspace != self.prefs['shortcut_RCtrlLoadWorkspace'] or shortcut_RCtrlSaveWorkspace != self.prefs['shortcut_RCtrlSaveWorkspace'] or shortcut_RCtrlAttach != self.prefs['shortcut_RCtrlAttach'] or shortcut_RCtrlClose != self.prefs['shortcut_RCtrlClose'] or check_CtrlC_4_Copy != self.prefs['R_console_Ctrl_C_4_copy'] or check_CtrlQ_break != self.prefs['R_console_Ctrl_Q_break'] or check_Escape_break != self.prefs['R_console_Escape_break']:
                    shortcut_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Key shortcuts have changed:\nplease restart gedit for changed to become effective!" )
                    shortcut_dialog.run()
                    shortcut_dialog.destroy()

                    self.prefs['shortcut_RCtrlLine'] = shortcut_RCtrlLine
                    self.prefs['shortcut_RCtrlSel'] = shortcut_RCtrlSel
                    self.prefs['shortcut_RCtrlAll'] = shortcut_RCtrlAll
                    self.prefs['shortcut_RCtrlBlock1Run'] = shortcut_RCtrlBlock1Run
                    self.prefs['shortcut_RCtrlBlock1Def'] = shortcut_RCtrlBlock1Def
                    self.prefs['shortcut_RCtrlBlock2Run'] = shortcut_RCtrlBlock2Run
                    self.prefs['shortcut_RCtrlBlock2Def'] = shortcut_RCtrlBlock2Def
                    self.prefs['shortcut_RCtrlNewTab'] = shortcut_RCtrlNewTab
                    self.prefs['shortcut_RCtrlConfig'] = shortcut_RCtrlConfig
                    self.prefs['shortcut_RCtrlLoadWorkspace'] = shortcut_RCtrlLoadWorkspace
                    self.prefs['shortcut_RCtrlSaveWorkspace'] = shortcut_RCtrlSaveWorkspace
                    #self.prefs['shortcut_RCtrlHelpSel'] = shortcut_RCtrlHelpSel
                    #self.prefs['shortcut_RCtrlShowSel'] = shortcut_RCtrlShowSel
                    #self.prefs['shortcut_RCtrlEditSel'] = shortcut_RCtrlEditSel
                    self.prefs['shortcut_RCtrlAttach'] = shortcut_RCtrlAttach
                    self.prefs['shortcut_RCtrlClose'] = shortcut_RCtrlClose
                    self.prefs['R_console_Ctrl_C_4_copy'] = check_CtrlC_4_Copy
                    self.prefs['R_console_Ctrl_Q_break'] = check_CtrlQ_break
                    self.prefs['R_console_Escape_break'] = check_Escape_break

        ChangeShortcuts_dialog.destroy()
        
    def ButtonSidePanelOptions_clicked(self,widget):
        SidePanelOptions_ui = gtk.glade.XML(self.get_data_dir()+"/SidePanelOptions.glade")
        
        check_IncludeLandmarksCheck = SidePanelOptions_ui.get_widget("IncludeLandmarksCheck")
        check_IncludeLandmarksCheck.set_active(self.prefs['R_structure_landmarks'])

        check_IncludeFunctionsCheck = SidePanelOptions_ui.get_widget("IncludeFunctionsCheck")
        check_IncludeFunctionsCheck.set_active(self.prefs['R_structure_functions'])

        check_IncludeDataframesCheck = SidePanelOptions_ui.get_widget("IncludeDataframesCheck")
        check_IncludeDataframesCheck.set_active(self.prefs['R_structure_dataframes'])

        SidePanelOptions_dialog = SidePanelOptions_ui.get_widget("SidePanelOptionsDialog")

        response = SidePanelOptions_dialog.run()
        if response == -2: #OK button
            # Collect the data: save the info and update the side panel:
            self.prefs['R_structure_landmarks'] = check_IncludeLandmarksCheck.get_active()
            self.prefs['R_structure_functions'] = check_IncludeFunctionsCheck.get_active()
            self.prefs['R_structure_dataframes'] = check_IncludeDataframesCheck.get_active()
            # Update the panels of all windows:
            for window in self._instances.keys():
                self._instances[window]._rstructurepanel.create_pattern_matcher()
                self._instances[window]._rstructurepanel.on_force_refresh(None)
            
        SidePanelOptions_dialog.destroy()

    def ButtonOk_clicked(self,widget):
        # Make a copy of the old values to see what changed:
        old_prefs = self.prefs.copy()
        
        # Did the user define a color for any of the prompts?
        prompt_color_defined = False

        # Retrieve the data first:
        check_box_autostart_R = self.ui.get_widget("AutostartR")
        self.prefs['autostart_R_console'] = check_box_autostart_R.get_active()

        check_box_use_doc_dir = self.ui.get_widget("UseDocDirectory")
        self.prefs['use_current_document_directory'] = check_box_use_doc_dir.get_active()

        check_box_show_message = self.ui.get_widget("ShowMessageCheck")
        self.prefs['show_messages_and_warnings'] = check_box_show_message.get_active()

        check_box_attach_R = self.ui.get_widget("StartRAttached")
        self.prefs['RConsole_start_attached'] = check_box_attach_R.get_active()

        check_box_autostart_script = self.ui.get_widget("AutostartScriptCheck")
        self.prefs['autostart_R_script'] = check_box_autostart_script.get_active()

        file_chooser_autostart_script = self.ui.get_widget("AutorunScriptPath")
        self.prefs['autostart_R_script_path'] = file_chooser_autostart_script.get_filename()
        if self.prefs['autostart_R_script_path'] == None:
            self.prefs['autostart_R_script'] = False
        else:
            # Make the path relative to the plugin's location
            print "Make AutorunScriptPath relative"

        spin_max_lines_as_text = self.ui.get_widget("MaxLinesToSendSpin")
        self.prefs['max_lines_as_text'] = spin_max_lines_as_text.get_value_as_int()

        check_box_HTML_help = self.ui.get_widget("HTMLHelpCheck")
        self.prefs['HTML_help'] = check_box_HTML_help.get_active()

        check_box_echo_commands = self.ui.get_widget("EchoPipedCommandsCheck")
        self.prefs['echo_commands'] = check_box_echo_commands.get_active()

        check_box_advance_line = self.ui.get_widget("AdvanceLineCheck")
        self.prefs['advance_to_next_line'] = check_box_advance_line.get_active()

        check_box_skip_empty_and_comment = self.ui.get_widget("SkipEmptyAndCommentCheck")
        self.prefs['skip_empty_and_comment_lines'] = check_box_skip_empty_and_comment.get_active()

        check_box_audible_bell = self.ui.get_widget("AudibleBell")
        self.prefs['audible_bell'] = check_box_audible_bell.get_active()

        check_box_visible_bell = self.ui.get_widget("VisibleBell")
        self.prefs['visible_bell'] = check_box_visible_bell.get_active()

        check_box_scroll_on_keystroke = self.ui.get_widget("ScrollOnKeystroke")
        self.prefs['scroll_on_keystroke'] = check_box_scroll_on_keystroke.get_active()

        check_box_scroll_on_output = self.ui.get_widget("ScrollOnOutput")
        self.prefs['scroll_on_output'] = check_box_scroll_on_output.get_active()
        
        edit_scrollback_lines = self.ui.get_widget("ScrollbackLines")
        try:
            no_lines = int(edit_scrollback_lines.get_text())
        except:
            error_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "The number of scrollback lines must be a positive integer!" )
            error_dialog.run()
            error_dialog.destroy()
            return
        if no_lines < 0:
            error_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "The number of scrollback lines must be a positive integer!" )
            error_dialog.run()
            error_dialog.destroy()
            return
        self.prefs['scrollback_lines'] = no_lines

        radio_button_cursor_blink_system = self.ui.get_widget("BlinkSystem")
        radio_button_cursor_blink_on = self.ui.get_widget("BlinkOn")
        radio_button_cursor_blink_off = self.ui.get_widget("BlinkOff")
        if radio_button_cursor_blink_system.get_active():
            self.prefs['cursor_blink'] = "system"
        elif radio_button_cursor_blink_on.get_active():
            self.prefs['cursor_blink'] = "on"
        elif radio_button_cursor_blink_off.get_active():
            self.prefs['cursor_blink'] = "off"

        radio_button_cursor_shape_block = self.ui.get_widget("ShapeBlock")
        radio_button_cursor_shape_ibeam = self.ui.get_widget("ShapeIBeam")
        radio_button_cursor_shape_underline = self.ui.get_widget("ShapeUnderline")
        if radio_button_cursor_shape_block.get_active():
            self.prefs['cursor_shape'] = "block"
        elif radio_button_cursor_shape_ibeam.get_active():
            self.prefs['cursor_shape'] = "ibeam"
        elif radio_button_cursor_shape_underline.get_active():
            self.prefs['cursor_shape'] = "underline"

        color_button_foreground1 = self.ui.get_widget("ForegroundColor1")
        self.prefs['foreground1'] = color_button_foreground1.get_color().to_string()

        color_button_background1 = self.ui.get_widget("BackgroundColor1")
        self.prefs['background1'] = color_button_background1.get_color().to_string()

        combo_box_prompt_color1 = self.ui.get_widget("PromptColor1")
        self.prefs['prompt_color1'] = self.xterm_color_from_index(combo_box_prompt_color1.get_active())
        
        color_button_foreground2 = self.ui.get_widget("ForegroundColor2")
        self.prefs['foreground2'] = color_button_foreground2.get_color().to_string()

        color_button_background2 = self.ui.get_widget("BackgroundColor2")
        self.prefs['background2'] = color_button_background2.get_color().to_string()

        combo_box_prompt_color2 = self.ui.get_widget("PromptColor2")
        self.prefs['prompt_color2'] = self.xterm_color_from_index(combo_box_prompt_color2.get_active())
        
        color_button_foreground3 = self.ui.get_widget("ForegroundColor3")
        self.prefs['foreground3'] = color_button_foreground3.get_color().to_string()

        color_button_background3 = self.ui.get_widget("BackgroundColor3")
        self.prefs['background3'] = color_button_background3.get_color().to_string()

        combo_box_prompt_color3 = self.ui.get_widget("PromptColor3")
        self.prefs['prompt_color3'] = self.xterm_color_from_index(combo_box_prompt_color3.get_active())
        
        check_box_tab_name_in_prompt = self.ui.get_widget("TabNameInPrompt")
        self.prefs['tab_name_in_prompt'] = check_box_tab_name_in_prompt.get_active()
        
        font_button = self.ui.get_widget("CurrentFont")
        self.prefs['font_name'] = font_button.get_font_name()

        # Save the preferences:
        self.save_prefs()
        
        self.dialog.destroy()

        # See what changed:
        vte1_console_changed = False
        vte1_R_options_changed = False
        vte2_console_changed = False
        vte2_R_options_changed = False
        vte3_console_changed = False
        vte3_R_options_changed = False

        # The ones affecting all consoles:
        if (old_prefs['audible_bell'] != self.prefs['audible_bell']) or (old_prefs['cursor_blink'] != self.prefs['cursor_blink']) or (old_prefs['cursor_shape'] != self.prefs['cursor_shape']) or (old_prefs['emulation'] != self.prefs['emulation']) or (old_prefs['font_name'] != self.prefs['font_name']) or (old_prefs['scroll_on_keystroke'] != self.prefs['scroll_on_keystroke']) or (old_prefs['scroll_on_output'] != self.prefs['scroll_on_output']) or (old_prefs['scrollback_lines'] != self.prefs['scrollback_lines']) or (old_prefs['visible_bell'] != self.prefs['visible_bell']) or (old_prefs['word_chars'] != self.prefs['word_chars']) or (old_prefs['echo_commands'] != self.prefs['echo_commands']):
            vte1_console_changed = True
            vte2_console_changed = True
            vte3_console_changed = True
        if (old_prefs['tab_name_in_prompt'] != self.prefs['tab_name_in_prompt']) or (old_prefs['HTML_help'] != self.prefs['HTML_help']):
            vte1_R_options_changed = True
            vte2_R_options_changed = True
            vte3_R_options_changed = True

        # VTE1 specifically:
        if (old_prefs['background1'] != self.prefs['background1']) or (old_prefs['foreground1'] != self.prefs['foreground1']):
            vte1_console_changed = True
        if (old_prefs['prompt_color1'] != self.prefs['prompt_color1']):
            vte1_R_options_changed = True
            if self.prefs['prompt_color1'] != None:
                prompt_color_defined = True

        # VTE2 specifically:
        if (old_prefs['background2'] != self.prefs['background2']) or (old_prefs['foreground2'] != self.prefs['foreground2']):
            vte2_console_changed = True
        if (old_prefs['prompt_color2'] != self.prefs['prompt_color2']):
            vte2_R_options_changed = True
            if self.prefs['prompt_color2'] != None:
                prompt_color_defined = True
        
        # VTE3 specifically:
        if (old_prefs['background3'] != self.prefs['background3']) or (old_prefs['foreground3'] != self.prefs['foreground3']):
            vte3_console_changed = True
        if (old_prefs['prompt_color3'] != self.prefs['prompt_color3']):
            vte3_R_options_changed = True
            if self.prefs['prompt_color3'] != None:
                prompt_color_defined = True
                
        # Warn the user about the side effects of color promts!
        if prompt_color_defined:
            warning_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Please note that using COLORED PROMPTS has a side effect when browsing R's history (keys UP and DOWN).\nPlease see the manual for details." )
            warning_dialog.run()
            warning_dialog.destroy()

        # Get the R prompts to update themselves:
        for i in list(self._instances.keys()):
            rctrlhelper = self._instances[i]
            rctrlhelper.update_R_consoles(vte1_console_changed,vte2_console_changed,vte3_console_changed,vte1_R_options_changed,vte2_R_options_changed,vte2_R_options_changed)

    def save_prefs(self):
        try:
            pref_file = open(os.path.expanduser("~/.rgedit-preferences"),"w")
            pickle.dump(self.prefs,pref_file)
            close(pref_file)
        except:
            pass
        

    def ButtonCancel_clicked(self,widget):
        self.dialog.destroy()

    def prompt_string(self,tab_number,tab_name):
        # Given the prompt settings, produce the appropriate R commands
        prompt_string = ""
        continue_string = ""
        xterm_color = self.xterm_16_color_from_string(self.prefs['prompt_color'+str(tab_number)])
        if xterm_color != "":
            # Add the color bits:
            prompt_string = prompt_string + "\\x1b" + xterm_color
            continue_string = continue_string + "\\x1b" + xterm_color
        if self.prefs['tab_name_in_prompt'] == True:
            # Add an extra character at the begining of the prompt to make it more obvious:
            prompt_string = prompt_string + tab_name
            continue_string = continue_string + tab_name
        # Add the middle of the prompt:
        prompt_string = prompt_string + "> "
        continue_string = continue_string + "+ "
        # and the final part (if any):
        if xterm_color != "":
            prompt_string = prompt_string + "\\x1b[33;0m"
            continue_string = continue_string + "\\x1b[33;0m"

        # Concate all these to get the full R code:
        return "options( prompt=\"" + prompt_string + "\", continue=\"" + continue_string + "\" )\n"

    def xterm_16_color_from_string(self,color_name):
        # Get the appropriate xterm escape sequence for the named color (if any):
        xterm_colors = {
            'black'    : '[1;30m',
            'red'      : '[1;31m',
            'green'    : '[1;32m',
            'yellow'   : '[1;33m',
            'blue'     : '[1;34m',
            'magenta'  : '[1;35m',
            'cyan'     : '[1;36m',
            'white'    : '[1;37m'
        }
        if color_name in xterm_colors:
            return xterm_colors[color_name]
        else:
            return ""

    def xterm_color_to_index(self,color_name):
        # Get the appropriate xterm escape sequence for the named color (if any):
        xterm_colors = {
            'black'    : 0,
            'red'      : 1,
            'green'    : 2,
            'yellow'   : 3,
            'blue'     : 4,
            'magenta'  : 5,
            'cyan'     : 6,
            'white'    : 7
        }
        if color_name == None:
            return 0
        elif color_name in xterm_colors:
            return xterm_colors[color_name]+1
        else:
            return -1

    def xterm_color_from_index(self,color_index):
        # Get the appropriate xterm escape sequence for the named color (if any):
        xterm_colors = {
            0          :'black',
            1          :'red',
            2          :'green',
            3          :'yellow',
            4          :'blue',
            5          :'magenta',
            6          :'cyan',
            7          :'white'
        }
        if color_index == 0:
            return None
        elif color_index in xterm_colors:
            return xterm_colors[color_index-1]
        else:
            return None


########################################################################
#                           The Wizard stuff
########################################################################

# Get the text from  collection of XML nodes:
def getText_from_XML(nodelist):
    rc = ""
    for node in nodelist:
        if node.nodeType == node.TEXT_NODE:
            rc = rc + node.data
    return rc

# Class implementing the wizard-wide about box:
class RWizard_AboutBox:

    def __init__(self):
        # Init:
        self.path = None # the path used for finding icons and stuff
        self.name = None
        self.version = None
        self.copyright = None
        self.comments = None
        self.license = None
        self.website = None
        self.authors = None 
        self.documenters = None
        self.artists = None
        self.translator_credits = None
        self.logo_icon_name = None
        
    def do_process_about(self,xml_node):
        # Get the about info:
        if xml_node.hasAttribute("name"):
            self.name = xml_node.getAttribute("name")
        if xml_node.hasAttribute("version"):
            self.version = xml_node.getAttribute("version")
        if xml_node.hasAttribute("copyright"):
            self.copyright = xml_node.getAttribute("copyright")
        if xml_node.hasAttribute("comments"):
            self.comments = xml_node.getAttribute("comments")
        if xml_node.hasAttribute("license"):
            self.license = xml_node.getAttribute("license")
        if xml_node.hasAttribute("website"):
            self.website = xml_node.getAttribute("website")
        if xml_node.hasAttribute("authors"):
            self.authors = xml_node.getAttribute("authors").split(",")
        if xml_node.hasAttribute("documenters"):
            self.documenters = xml_node.getAttribute("documenters")
        if xml_node.hasAttribute("artists"):
            self.artists = xml_node.getAttribute("artists")
        if xml_node.hasAttribute("translator_credits"):
            self.translator_credits = xml_node.getAttribute("translator_credits")
        if xml_node.hasAttribute("logo_icon_name"):
            self.logo_icon_name = self.path + xml_node.getAttribute("logo_icon_name")
        return True
        
    def show(self):
        # Display the about info:
        about_dialog = gtk.AboutDialog()
        about_dialog.set_name(self.name)
        about_dialog.set_version(self.version)
        about_dialog.set_copyright(self.copyright)    
        about_dialog.set_comments(self.comments)
        about_dialog.set_license(self.license)
        about_dialog.set_website(self.website)
        about_dialog.set_authors(self.authors) 
        about_dialog.set_documenters(self.documenters)
        about_dialog.set_artists(self.artists)
        about_dialog.set_translator_credits(self.translator_credits)
        about_dialog.set_logo(gtk.gdk.pixbuf_new_from_file(self.logo_icon_name))
        
        about_dialog.show()
        about_dialog.run()
        about_dialog.destroy()
        

# Class implementing a template:
class RWizard_Template:

    def __init__(self):
        # Init:
        self.RawText = None
        
    def do_process_template(self,xml_node):
        # Get the node's text (i.e., the raw template):
        self.RawText =  getText_from_XML(xml_node.childNodes)
        
        return True
        
    def update(self,variables):
        # Update the template using the variable values in the given dictionary:
        new_template = self.RawText
        
        # Process the $[Python ... $] python directives:
        new_template = self.process_directives(new_template,variables)
        if new_template == None:
            # Some error has occured:
            return None
        
        # Replace the ${xxx} with xxx's value:
        for variable in variables:
            new_template = new_template.replace( "${" + variable + "}", str(variables[variable]) )
        return new_template
        
    def process_directives(self,template,variables):
        # Process the $[ ... $] directives:
        # For now, only Python scripting executed:
        python_directive_start = template.find("$[Python")
        while python_directive_start != -1:
            # Found a directive: get the whole expression
            python_directive_end = template.find("$]",python_directive_start)
            if python_directive_end == -1:
                question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Python directives must end with $]...." )
                response = question_dialog.run()
                question_dialog.destroy()
                return None
                
            # Evaluate the condition:
            python_directive = template[(python_directive_start+len("$[Python")):python_directive_end]
            #print python_directive
            for variable in variables:
                python_directive = python_directive.replace( "${" + variable + "}", str(variables[variable]) )
            python_directive = eval(python_directive,__builtins__)
            #python_directive = eval(python_directive, {"__builtins__":None}, {})
            
            # And replace the result appropriately
            if python_directive == None:
                python_directive = ""
            else:
                python_directive = str(python_directive)
            template = template.replace( template[python_directive_start:(python_directive_end+len("$]"))], python_directive )
            
            # Search for the next directive:
            python_directive_start = template.find("$[Python")
            
        return template
            
        
    # Debug printing:
    def print_debug(self):
        print "Template: " +  str(self.RawText)
        
        
# Class implementing a varibale within the block:
class RWizard_Variable:

    def __init__(self):
        # Init:
        self.Name = None
        self.Description = False
        self.Required = False
        self.Type = None
        self.Default = None
        self.Singlechoice = True
        self.ToolTip = None
        self.ListValues = []
        self.GtkControl = None # the associated Gtk control (if any)
        self.ValueDefined = False # has the variable's value been already defined?
        self.Value = None # and the actual value (if any)
        
    def get_value(self):
        # Return the value adjusted for final usage (e.g., for comboboxes return the actually selected string):
        if self.Type.lower() == "list":
            return self.ListValues[self.Value]
        else:
            return self.Value
        
    def do_process_variable(self,xml_node):
        # Read the attributes:
        if xml_node.hasAttribute("name"):
            self.Name = xml_node.getAttribute("name")
        else:
            print "A variable must have a name!"
            return False
            
        if xml_node.hasAttribute("description"):
            self.Description = xml_node.getAttribute("description")
        else:
            print "A variable must have a description!"
            return False
            
        if xml_node.hasAttribute("required"):
            self.Required = (xml_node.getAttribute("required").lower() == "true")

        if xml_node.hasAttribute("type"):
            self.Type = xml_node.getAttribute("type")
        else:
            print "A variable must have a type!"
            return False
            
        if xml_node.hasAttribute("default"):
            self.Default = xml_node.getAttribute("default")
            
        if xml_node.hasAttribute("singlechoice"):
            self.Singlechoice = xml_node.getAttribute("singlechoice")
            
        if xml_node.hasAttribute("tooltip"):
            self.ToolTip = xml_node.getAttribute("tooltip")
            
        if self.Type == "list":
            # Try to get the values:
            values_nodes = xml_node.getElementsByTagName("value")
            if values_nodes == None and len(values_nodes) == 0:
                print "Variables of type \"list\" must have at least one value defined!"
                return False
            else:
                # Get the values:
                for value_node in values_nodes:
                    if value_node.hasAttribute("name"):
                        self.ListValues = self.ListValues + [value_node.getAttribute("name")]
            if len(self.ListValues) == 0:
                print "Variables of type \"list\" must have at least one value defined!"
        elif self.Type == "editablelist":
            # Try to get the values:
            values_nodes = xml_node.getElementsByTagName("value")
            if values_nodes == None and len(values_nodes) == 0:
                print "Variables of type \"editablelist\" must have at least one value defined!"
                return False
            else:
                # Get the values:
                for value_node in values_nodes:
                    if value_node.hasAttribute("name"):
                        self.ListValues = self.ListValues + [value_node.getAttribute("name")]
            if len(self.ListValues) == 0:
                print "Variables of type \"editablelist\" must have at least one value defined!"
            
        return True
        
    # Debug printing:
    def print_debug(self):
        print "Variable: " +  str(self.Name) + " [" + str(self.Description) + " type=" + str(self.Type) + " default=" + str(self.Default) + "]"
        if str(self.Type) == "list":
            print "   Values: " + str(self.ListValues)

# Class implementing a block within the vars:
class RWizard_Block:

    def __init__(self):
        # Init:
        self.Title = None
        self.Rselector = False
        self.Layout = "vertical"  # can be "vertical", "horizontal" or "grid"
        self.Variables = [] # the list of variables
        
        # Dialog params;
        self.max_initial_width = 600
        self.max_initial_height = 300
        
    def do_process_block(self,xml_node):
        # Get the title:
        if xml_node.hasAttribute("title"):
            self.Title = xml_node.getAttribute("title")
            
        # and the other optional attributes:
        if xml_node.hasAttribute("rselector"):
            self.Rselector = xml_node.getAttribute("rselector")
        if xml_node.hasAttribute("layout"):
            self.Layout = xml_node.getAttribute("layout")
            
        # Parse the variables within this block:
        variables_node = xml_node.getElementsByTagName("variable")
        if variables_node == None or len(variables_node) == 0:
            print "Blocks must have at least one variable!"
            return False
        for variable_node in variables_node:
            variable = RWizard_Variable()
            if not variable.do_process_variable(variable_node):
                return False
            else:
                self.Variables = self.Variables + [variable]
                
        if len(self.Variables) == 0:
            print "There must be at least one variable defined for each block!"
            return False
        
        return True
        
    # Debug printing:
    def print_debug(self):
        print "Block: " +  str(self.Title) + "[rselector=" + str(self.Rselector) + " layout=" + str(self.Layout) + "]"
        for variable in self.Variables:
            variable.print_debug()
            
    def run(self,wizard,is_previous,is_next,is_last,selection_as,selection_text):
        # Construct and display the wizard block and collect user input:
        # Return the following codes: 0 = cancel, -1 = previous, 1 = next/OK, 2 = OK & just run the data
        label = gtk.Label(self.Title)
        dialog = gtk.Dialog(wizard.Description,
                           None,
                           gtk.DIALOG_DESTROY_WITH_PARENT,)
        dialog.vbox.pack_start(label)
        label.show()
        
        ## Embed the controls in a scrollable area, just in case they tend to be bigger than the available screen space:
        #holder_scrollable = gtk.ScrolledWindow()
        #holder_scrollable.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
        #holder_scrollable.show()
        #holder_layout = gtk.Layout()
        #holder_layout.show()
        
        # Start adding the required widgets for each variable:
        container_vbox = gtk.VBox()
        container_vbox.show()
        for variable in self.Variables:
            self.add_widgets_for_variable(container_vbox,variable,selection_as,selection_text)
        #holder_layout.put(container_vbox,0,0)
        # And adjust the size accordingly
        #holder_layout.set_size(self.max_width,self.max_height)
        
        #holder_scrollable.add(holder_layout)
        #dialog.vbox.pack_start(holder_scrollable)
        dialog.vbox.pack_start(container_vbox)
        
        # The buttons:
        about_button = dialog.add_button("About", 1303 ) # About the wizard
        about_button.set_sensitive( wizard.AboutInfo != None )
        about_button.set_tooltip_text("About the wizard...")
        
        help_button = dialog.add_button("Help", 1304 ) # Help on the dialog
        help_button.set_sensitive( wizard.Help != None )
        help_button.set_tooltip_text("Wizard's help info...")
        
        #dialog.action_area.add(gtk.HSeparator())
        back_button = dialog.add_button("Back", 1299 ) # Going back
        back_button.set_sensitive( is_previous )
        back_button.set_tooltip_text("Go to previous block...")
        
        if is_last:
            ok_button = dialog.add_button("Inspect code", 1302 ) # OK and end
            ok_button.set_tooltip_text("Inspect the generated R code...")
            run_button = dialog.add_button("Run code!", 1305 ) # Ok and just run
            run_button.set_tooltip_text("I trust the wizard: go ahead and run the generated R code...")
        else:
            next_button = dialog.add_button("Next", 1301 ) # Next
            next_button.set_sensitive( is_next )
            next_button.set_tooltip_text("Continue to next block...")
            
        cancel_button = dialog.add_button("Cancel", 1300 ) # Cancel
        cancel_button.set_tooltip_text("Cancel the wizard...")
        
        # The initial dialog size:
        initial_size = dialog.get_size()
        if initial_size[0] > self.max_initial_width:
            initial_width = self.max_initial_width
        else:
            initial_width = initial_size[0]
        if initial_size[1] > self.max_initial_height:
            initial_height = self.max_initial_height
        else:
            initial_height = initial_size[1]
        dialog.resize( initial_width, initial_height )
        
        ret_val = 999
        while ret_val == 999:
            # Allow the user to interact with it and collect the response;
            response = dialog.run()
            
            # Process the user response value:
            if response == 1300:
                # Aborted: don't collect the data!
                ret_val = 0
            elif response == 1301 or response == 1302:
                # Forward or OK: collect the data!
                if not self.collect_data(dialog):
                    ret_val = 999 # don't close the dialog!!!
                else:
                    ret_val = 1
            elif response == 1299:
                # Back: collect the data!
                self.collect_data(dialog)
                ret_val = -1
            elif response == 1303:
                # Display the about info:
                wizard.AboutInfo.show()
                ret_val = 999 # don't close the dialog!!!
            elif response == 1304:
                # Display the help info:
                if wizard.Help:
                    if wizard.Help[0] == "?":
                        # R entity:
                        do_send_to_R(wizard.Help[1:]+"\n",wizard._rwizardengine._rctrlwindowhelper.R_widget,False)
                    else:
                        webbrowser.open(wizard.Help)
                ret_val = 999 # don't close the dialog!!!
            elif response == 1305:
                # Just run the code!
                if not self.collect_data(dialog):
                    ret_val = 999 # don't close the dialog!!!
                else:
                    ret_val = 2
            else:
                # Aborted: don't collect the data!
                ret_val = 0
            
        # Destroy the dialog and return the value:
        dialog.destroy()
        return ret_val
            
    def add_widgets_for_variable(self,container_vbox,variable,selection_as,selection_text):
        # Add the appropriate widgets for the variable in the holder_layout at the positions given by self.current_x and self.current_y (and update them appropriately):        
        container_hbox = gtk.HBox()
        container_hbox.show()
        
        var_text = ("<b>*</b>" if variable.Required else "") + variable.Description + str(" (<b><tt>") + variable.Name + str("</tt></b>): ")
        
        if variable.Type.lower() == "text":
            # text widget:
            var_label = gtk.Label()
            var_label.set_markup(var_text)
            if variable.ToolTip:
                var_label.set_tooltip_markup(variable.ToolTip)
            var_label.show()
            container_hbox.add(var_label)
            
            var_edit = gtk.Entry()
            var_edit.set_has_frame(True)
            if variable.ToolTip:
                var_edit.set_tooltip_markup(variable.ToolTip)
            var_edit.show()
            container_hbox.add(var_edit)
            
            variable.GtkControl = var_edit
            if variable.Default:
                var_edit.set_text(variable.Default)
                
            if variable.ValueDefined:
                var_edit.set_text(variable.Value)
            elif selection_as != None and selection_as.lower() == variable.Name.lower() and selection_text != None: 
                var_edit.set_text(selection_text)
        elif variable.Type.lower() == "list":
            # list widget:
            if variable.Singlechoice.lower() == "true":
                # it's a combobox!
                var_label = gtk.Label()
                var_label.set_markup(var_text)
                if variable.ToolTip:
                    var_label.set_tooltip_markup(variable.ToolTip)
                var_label.show()
                container_hbox.add(var_label)
                
                var_combo = gtk.combo_box_new_text()
                for value in variable.ListValues:
                    var_combo.append_text(value)
                default_choice = -1
                try:
                    default_choice = int(variable.Default)
                except ValueError:
                    default_choice = -1
                var_combo.set_active(default_choice)
                if variable.ToolTip:
                    var_combo.set_tooltip_markup(variable.ToolTip)
                var_combo.show()
                container_hbox.add(var_combo)
                
                variable.GtkControl = var_combo
                if variable.ValueDefined:
                    var_combo.set_active(variable.Value)
        elif variable.Type.lower() == "editablelist":
            # editablelist widget:
            if variable.Singlechoice.lower() == "true":
                # it's a comboboxentry!
                var_label = gtk.Label()
                var_label.set_markup(var_text)
                if variable.ToolTip:
                    var_label.set_tooltip_markup(variable.ToolTip)
                var_label.show()
                container_hbox.add(var_label)
                
                var_combo_edit = gtk.combo_box_entry_new_text()
                for value in variable.ListValues:
                    var_combo_edit.append_text(value)
                var_combo_edit.get_child().set_text(variable.Default)
                if variable.ToolTip:
                    var_combo_edit.set_tooltip_markup(variable.ToolTip)
                var_combo_edit.show()
                container_hbox.add(var_combo_edit)
                
                variable.GtkControl = var_combo_edit
                if variable.ValueDefined:
                    var_combo_edit.get_child().set_text(variable.Value)
        elif variable.Type.lower() == "bool":
            # checkbox:
            var_label = gtk.Label()
            var_label.set_markup(var_text)
            if variable.ToolTip:
                var_label.set_tooltip_markup(variable.ToolTip)
            var_label.show()
            container_hbox.add(var_label)
            
            var_check = gtk.CheckButton()
            if variable.ToolTip:
                var_check.set_tooltip_markup(variable.ToolTip)
            var_check.show()
            container_hbox.add(var_check)
            
            variable.GtkControl = var_check
            if variable.Default:
                var_check.set_active(variable.Default.lower() == "true")
                
            if variable.ValueDefined:
                var_check.set_active(variable.Value)
                
        # add this row to the dialog:        
        container_vbox.add(container_hbox)
        
    def collect_data(self,dialog):
        # Collect the user-introduced data and save it in the appropriate places: return True if all required variables are defined
        for variable in self.Variables:
            self.collect_data_for_variable(variable)
            if variable.Required and not variable.ValueDefined:
                question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, 'Required variable "' + variable.Name + '" is undefined!' )
                response = question_dialog.run()
                question_dialog.destroy()
                return False
        return True
            
    def collect_data_for_variable(self,variable):
        if variable.GtkControl == None:
            print "Error: variable.GtkControl should have been defined!"
            variable.Value = None
            variable.ValueDefined = False
            return
            
        if variable.Type.lower() == "text":
            # gtk.Entry:
            variable.Value = variable.GtkControl.get_text()
            variable.ValueDefined = (variable.Value.strip() != "")
        elif variable.Type.lower() == "list":
            # list widget:
            if variable.Singlechoice.lower() == "true":
                # gtk.combo_box_new_text():
                variable.Value = variable.GtkControl.get_active()
                variable.ValueDefined = True
        elif variable.Type.lower() == "editablelist":
            # list widget:
            if variable.Singlechoice.lower() == "true":
                # gtk.combo_box_new_text():
                variable.Value = variable.GtkControl.get_child().get_text()
                variable.ValueDefined = True
        elif variable.Type.lower() == "bool":
            # gtk.CheckButton()
            variable.Value = variable.GtkControl.get_active()
            variable.ValueDefined = True
        else:
            variable.Value = None
            variable.ValueDefined = False
       
    
# This class implements a single wizard:
class RWizard:
    
    def __init__(self,_rwizardengine):
        # Init the wizard:
        self._rwizardengine = _rwizardengine
        self.Name = None
        self.Description = None
        # The desired (i.e., suggested by the rwizard itself) menu, icon, toolbar status and keyboard shortuct:
        self.DesiredMenu = None
        self.DesiredIcon = None
        self.DesiredToolbar = None
        self.DesiredShortcut = None
        # ... and the actual (i.e., taking into account the user preferences and default rules) ones:
        self.ActualMenu = None
        self.ActualIcon = None
        self.ActualToolbar = None
        self.ActualShortcut = None
        # The list of blocks and the template:
        self.Blocks = []
        self.Template = None
        # About info and help:
        self.AboutInfo = None
        self.Help = None
        # Default button:
        self.DefaultButton = 0 # 0 = Just paste, 1 = Just run, 2 = Paste & run
        self.SelectionAs = None
        self.SelectedText = None # the selection text (if any) when the dialog is fired (to be used as instructed by SelectionAs)
        return
    
    # Try to load and create a wizard from the given file description and return True inf successful, False otherwise    
    def load(self,file_name):
        # Open the file for reading:
        try:
            wizard_doc = minidom.parse( file_name )
        except:
            print "Error opening & parsing wizard file \"" + file_name + "\": ", sys.exc_info()[1]
            question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "Error opening & parsing wizard file \"" + file_name + "\":\n" + str(sys.exc_info()[1]) + "\n\nRgedit plugin cannot continue! Please fix the problem..." )
            response = question_dialog.run()
            question_dialog.destroy()
            return False
            
        # Proceed through the DOM and get the relevant stuff:
        root_node = wizard_doc.documentElement;
        if root_node.nodeName.lower() != 'rwizard':
            print "Error: rwizard xml expected, and instead got \"" + root_node.nodeName.lower() + "\"..."
            wizard_doc.unlink()
            return False;
            
        # Get the name and description:
        if not root_node.hasAttribute("name"):
            print "Error: rwizard must have a name!"
            wizard_doc.unlink()
            return False;
        self.Name = root_node.getAttribute("name")
        
        if root_node.hasAttribute("description"):
            self.Description = root_node.getAttribute("description")
        else:
            self.Description = self.Name
            
        if root_node.hasAttribute("menu"):
            self.DesiredMenu = root_node.getAttribute("menu")
        else:
            self.DesiredMenu = self.Name
            
        if root_node.hasAttribute("icon"):
            self.DesiredIcon = root_node.getAttribute("icon")
        else:
            self.DesiredIcon = self.Name
            
        if root_node.hasAttribute("toolbar"):
            self.DesiredToolbar = root_node.getAttribute("toolbar")
        else:
            self.DesiredToolbar = self.Name
            
        if root_node.hasAttribute("shortcut"):
            self.DesiredShortcut = root_node.getAttribute("shortcut")
        else:
            self.DesiredShortcut = self.Name
            
        if root_node.hasAttribute("defaultbutton"):
            if root_node.getAttribute("defaultbutton").lower() == "paste":
                self.DefaultButton = 0
            elif root_node.getAttribute("defaultbutton").lower() == "run":
                self.DefaultButton = 1
            elif root_node.getAttribute("defaultbutton").lower() == "paste and run":
                self.DefaultButton = 2
            else:
                print "Unknown value for the defaultbutton attribute :" + root_node.getAttribute("defaultbutton")

        if root_node.hasAttribute("selectionas"):
            self.SelectionAs = root_node.getAttribute("selectionas")

        # Process the about info:
        about_node = root_node.getElementsByTagName("about")
        if about_node != None:
            if len(about_node) == 1:
                if not self.do_process_about( about_node[0] ):
                    wizard_doc.unlink()
                    return False
            elif len(about_node) > 1:
                print "There must at most one \"about\" node inside a \"rwizard\""
                wizard_doc.unlink()
                return False
            
        # Process the help file, url or R entiry:
        help_node = root_node.getElementsByTagName("help")
        if help_node != None:
            if len(help_node) == 1:
                if not self.do_process_help( help_node[0] ):
                    wizard_doc.unlink()
                    return False
            elif len(help_node) > 1:
                print "There must at most one \"help\" node inside a \"rwizard\""
                wizard_doc.unlink()
                return False
            
        # Process the variables:
        vars_node = root_node.getElementsByTagName("vars")
        if vars_node != None and len(vars_node) == 1:
            if not self.do_process_vars( vars_node[0] ):
                wizard_doc.unlink()
                return False
        else:
            print "There must a single \"vars\" node inside a \"rwizard\""
            wizard_doc.unlink()
            return False
            
        # Process the script:
        script_node = root_node.getElementsByTagName("script")
        if script_node != None:
            if len(script_node) == 1:
                if not self.do_process_script( script_node[0] ):
                    wizard_doc.unlink()
                    return False
            elif len(script_node) > 1:
                print "There must at most one \"script\" node inside a \"rwizard\""
                wizard_doc.unlink()
                return False
            
        # Process the template:
        template_node = root_node.getElementsByTagName("template")
        if template_node != None and len(template_node) == 1:
            if not self.do_process_template( template_node[0] ):
                wizard_doc.unlink()
                return False
        else:
            print "There must a single \"template\" node inside a \"rwizard\""
            wizard_doc.unlink()
            return False
            
        # Reconcile the options requested by the izard with those defined by the user and the default ones:
        if self.DesiredMenu != None:
            self.ActualMenu = self.DesiredMenu
        else:
            self.ActualMenu = self._rwizardengine.get_menu(self.Name)
            
        if self.DesiredIcon != None:
            self.ActualIcon = self.DesiredIcon
        else:
            self.ActualIcon = self._rwizardengine.get_icon(self.Name)
            
        if self.DesiredToolbar != None:
            self.ActualToolbar = self.DesiredToolbar
        else:
            self.ActualToolbar = self._rwizardengine.get_toolbar(self.Name)
            
        if self.DesiredShortcut != None:
            self.ActualShortcut = self.DesiredShortcut
        else:
            self.ActualShortcut = self._rwizardengine.get_shortcut(self.Name)
            
        # Everything's ok:
        wizard_doc.unlink()
        return True
        
    def do_process_vars(self,xml_node):
        # Process the blocks inside this vars element:
        block_nodes = xml_node.getElementsByTagName("block")
        for block_node in block_nodes:
            if not self.do_process_block( block_node ):
                return False
        #if len(self.Blocks) == 0:
        #    print "There must be at least one block defined!"
        #    return False
        return True
        
    def do_process_about(self,xml_node):
        # Create the about dialog:
        self.AboutInfo = RWizard_AboutBox()
        self.AboutInfo.Name = self.Description
        self.AboutInfo.path = self._rwizardengine.path
        
        # Parse it!
        return self.AboutInfo.do_process_about(xml_node)
        
    def do_process_help(self,xml_node):
        # Try to get the help file:
        if xml_node.hasAttribute("file"):
            self.Help = "file://" + self._rwizardengine.path + xml_node.getAttribute("file")
        elif xml_node.hasAttribute("url"):
            self.Help = xml_node.getAttribute("url")
        elif xml_node.hasAttribute("rhelp"):
            self.Help = "?" + xml_node.getAttribute("rhelp")
        return True
            
    def do_process_block(self,xml_node):
        # Create a new block and read its contents:
        block = RWizard_Block()
        
        # Parse it!
        if not block.do_process_block(xml_node):
            return False
            
        # Add it to the blocks list:
        self.Blocks = self.Blocks + [block]
        
        return True
    
    def do_process_script(self,xml_node):
        # Process the script node:
        print "Processing script..."
        return True
    
    def do_process_template(self,xml_node):
        # Process the template node:
        self.Template = RWizard_Template()
        if not self.Template.do_process_template(xml_node):
            return False
        return True
    
    # Debug printing:
    def print_debug(self):
        print "Wizard: " +  " " + str(self.Name) + " [" + str(self.Description) + "]" + ": " + str(self.ActualMenu) + " " + str(self.ActualIcon) + " " + str(self.ActualToolbar) + " " + str(self.ActualShortcut)
        for block in self.Blocks:
            block.print_debug()
        self.Template.print_debug()
        
        
    # Run this wizard!
    def run(self):
        #print "Running wizard " + self.Description + " ..."
        # Let each block display itself and depending on the user response continue or abort:
        if len(self.Blocks) > 0:
            # Check if the selection is to be used:
            self.SelectedText = None
            if self.SelectionAs != None:
                # Then try to get it so that it can be used for the requested variable:
                doc = self._rwizardengine._window.get_active_document()
                if not doc:
                    return
                # See if anything is selected:
                if doc.get_has_selection():
                    sel_bounds = doc.get_selection_bounds()
                    self.SelectedText = doc.get_text(sel_bounds[0],sel_bounds[1])
            
        i = 0
        # Cycle in order to allow back from R code dialog:
        while True:
            finished_OK = False
            user_action = +2
            while i < len(self.Blocks):
                user_action = self.Blocks[i].run( self, i>0, i<(len(self.Blocks)-1), i==(len(self.Blocks)-1), self.SelectionAs, self.SelectedText )
                if user_action == 0:
                    # Abort the whole wizard...
                    finished_OK = False
                    return
                elif user_action == -1:
                    # Go back one step:
                    if i > 0:
                        i = i-1
                    else:
                        i = 0
                elif user_action == +1:
                    # Go forward one step or stop the process with OK:
                    if i < (len(self.Blocks)-1):
                        i = i+1
                    else:
                        finished_OK = True
                        break
                elif user_action == +2:
                    # Ok & just run the code!
                    finished_OK = True
                    break
                else:
                    print "Unknown block-level user action " + user_action + "!"
                    return
            
            if finished_OK or (len(self.Blocks) == 0):
                updated_template = self.update_template()
                if updated_template != None:
                    # Everything's ok; beautify the R source code:
                    # 1. Get rid of the empty lins at the begining and end (if any):
                    self.beautified_template = ""
                    lines = updated_template.split('\n')
                    from_top = 0
                    while from_top < len(lines):
                        if not lines[from_top].strip():
                            from_top += 1
                        else:
                            break
                    if from_top == len(lines):
                        # Empty text: nothing to do!
                        question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "The resulting R code is empty..." )
                        response = question_dialog.run()
                        question_dialog.destroy()
                        return
                    from_bottom = len(lines)-1
                    while from_bottom >= 0:
                        if not lines[from_bottom].strip():
                            from_bottom -= 1
                        else:
                            break
                    if from_bottom == 0:
                        # Empty text: nothing to do!
                        question_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "The resulting R code is empty..." )
                        response = question_dialog.run()
                        question_dialog.destroy()
                        return
                    for i in range(from_top,from_bottom+1):
                        self.beautified_template += lines[i] + '\n'
                        
                    if user_action == +2:
                        # Simply run the resulting code:
                        self.resulting_template = self.beautified_template
                        response = 1301
                    else:
                        # Ask the user what they wants to do with the resulting template:
                        self.ui = gtk.glade.XML(self._rwizardengine._plugin.get_data_dir()+"/WizardActions.glade")
                        self.dialog = self.ui.get_widget("WiardsActionsDialog")
                        
                        self.source_buffer = gtk.TextBuffer()
                        self.source_buffer.set_text(self.beautified_template)
                        self.source_view = self.ui.get_widget("SourceView")
                        self.source_view.set_buffer(self.source_buffer)
                        self.source_view.modify_font(pango.FontDescription('Monospace 10'))
                        
                        # Event handlers:
                        dic = { "on_InsertCommentCheck_toggled" : self.on_InsertCommentCheck_toggled }
                        #        "on_IndentSpin_value_changed" : self.on_IndentSpin_value_changed,
                        #        "on_IndentComboBox_changed" : self.on_IndentComboBox_changed }
                        self.ui.signal_autoconnect(dic)
                        
                        # Initial settings:
                        self.ui.get_widget("InsertCommentCheck").set_active(True)
                        #self.ui.get_widget("IndentComboBox").set_active(0) # Tabs initially
                
                        response = self.dialog.run()
                        self.resulting_template = self.source_buffer.get_text(self.source_buffer.get_start_iter(),self.source_buffer.get_end_iter())
                        self.dialog.destroy()
                    
                    # Process the response appropriately:
                    if response == 1299:
                        # Back: let the cycle resume from the last block:
                        i = len(self.Blocks)-1
                    elif response == 1300:
                        # Paste & run:
                        self.do_paste_R_code()
                        self.do_run_R_code()
                        return
                    elif response == 1301:
                        # Just run:
                        self.do_run_R_code()
                        return
                    elif response == 1302:
                        # Just paste:
                        self.do_paste_R_code()
                        return
                    else:
                        # Cancel:
                        return
                else:
                    # Abort required:
                    return
                
                #print self.beautified_template
                
    def do_paste_R_code(self):
        # Paste the R code at the cursor position:
        doc = self._rwizardengine._window.get_active_document()
        if not doc:
            return
        doc.insert_at_cursor(self.resulting_template)
        
    def do_run_R_code(self):
        # Run the R code through the current console (if any):
        if self._rwizardengine._rctrlwindowhelper.R_widget != None:
            do_send_to_R(self.resulting_template,self._rwizardengine._rctrlwindowhelper.R_widget,False)
                
    def on_InsertCommentCheck_toggled(self,widget):
        self.add_comment_to_R_code(widget.get_active())
        
    def add_comment_to_R_code(self,insert_comment):
        comment_id = "# RWizard "
        if insert_comment:
            # Insert the comment as the first line:
            comment = comment_id + '"' + self.Description + '" on ' + datetime.datetime.now().strftime("%A, %d %B %Y @ %H:%M:%S") + "\n"
            self.source_buffer.insert(self.source_buffer.get_start_iter(),comment)
            return comment
        else:
            # Try to remove the comment (should be the first line starting with "# RWizard "):
            first_line = self.source_buffer.get_text(self.source_buffer.get_iter_at_line_offset(0,0),self.source_buffer.get_iter_at_line_offset(1,0)).strip()
            if comment_id == first_line[:len(comment_id)]:
                # Remove the first line:
                self.source_buffer.delete(self.source_buffer.get_iter_at_line_offset(0,0),self.source_buffer.get_iter_at_line_offset(1,0))
            return None
                
    #def on_IndentSpin_value_changed(self,widget):
    #    if self.ui.get_widget("IndentRCodeCheckButton").get_active():
    #        self.indent_R_code(widget.get_value_as_int(),self.ui.get_widget("IndentComboBox").get_active()==0)
    #        
    #def on_IndentComboBox_changed(self,widget):
    #    if self.ui.get_widget("IndentRCodeCheckButton").get_active():
    #        self.indent_R_code(self.ui.get_widget("IndentSpin").get_value_as_int(),widget.get_active()==0)
    #        
    #def indent_R_code(self,indent,use_tabs):
    #    self.beautified_template = ""
    #    indent_text = ("\t" if use_tabs else " ")*indent
    #    lines = self.beautified_template_original.split('\n')
    #    comment = self.add_comment_to_R_code(self.ui.get_widget("InsertCommentCheck").get_active())
    #    if comment != None:
    #        lines = [comment.split('\n')[0]] + lines
    #    for line in lines:
    #        self.beautified_template += indent_text + line + "\n"
    #    self.source_buffer.set_text(self.beautified_template)
                
    def update_template(self):
        # Use the user input the complete the script template:
        #print "Filling in the script template:"
        #self.Template.print_debug()
        
        # First, create the list of variables with their values:
        variables = {} # use a dictionary of variables indexed by name
        for block in self.Blocks:
            for variable in block.Variables:
                if variable.ValueDefined:
                    variables[variable.Name] = variable.get_value()
                    
        # And then ask the template to update itself using these variables and return the resulting text:
        updated_template = self.Template.update(variables)
        
        # Return the updated template for further use:
        return updated_template
        

# Class implementing an item within prefs:
class Userprefs_Item:

    def __init__(self):
        # Init:
        self.Rwizard = None
        self.Menu = None
        self.Icon = None
        self.Toolbar = False
        self.Shortcut = None
    
    # Debug printing:
    def print_debug(self):
        print "Item: " +  " " + str(self.Rwizard) + " " + str(self.Menu) + " " + str(self.Icon) + " " + str(self.Toolbar) + " " + str(self.Shortcut)
        

# This class implements the wizards manager:
class RWizardEngine:
    def __init__(self,rctrlwindowhelper):
        # Init the wizards:
        self._rctrlwindowhelper = rctrlwindowhelper
        self._plugin = rctrlwindowhelper._plugin
        self._window = rctrlwindowhelper._window
        self.path = self._plugin.get_data_dir()+"/Wizards/"
        
        # Global defaults:
        self.RootMenuEntry = "Wizards"
        self.ShowOnToolbar = False
        self.ShortcutsActive = False
        # And specific, user-defined preferences:
        self.userprefs = []
        
        # Load the user preferences for wizards:
        self.load_user_prefs()
        
        # Load the wizards:
        self.wizards = self.load_wizards()
        # Sort them alphabetically by menu entry:
        if len(self.wizards) > 1:
            self.wizards.sort(key=lambda x: x.ActualMenu)
        
        # Debug print:
        #self.print_debug()
        
    # Try to read and load the defined wizards:
    def load_wizards(self):
        wizard_files = glob.glob(self.path+"*.xml")
        wizards = []
        for wizard_file in wizard_files:
            if not wizard_file.lower().endswith("userprefs.xml"): # ignore the userprefs.xml file
                wizards = wizards + [self.load_wizard(wizard_file)]
        return wizards
        
    # Try to load and create a wizard from the given file description:
    def load_wizard(self,file_name):
        #print "load_wizard: " + file_name
        rwizard = RWizard(self)
        if rwizard.load(file_name):
            # Debug print:
            #rwizard.print_debug()
            return rwizard
        else:
            # Debug print:
            #rwizard.print_debug()
            return None

    # Load the wizard user preferences:
    def load_user_prefs(self):
        # Open the file for reading:
        try:
            prefs_doc = minidom.parse( self.path + "userprefs.xml" )
        except:
            print "Error opening userprefs.xml!"
            return False
            
        # Proceed through the DOM and get the relevant stuff:
        root_node = prefs_doc.documentElement;
        if root_node.nodeName.lower() != 'rwizardsuserprefs':
            print "Error: rwizardsuserprefs xml expected, and instead got \"" + root_node.nodeName.lower() + "\"..."
            wizard_doc.unlink()
            return False;
            
        # Get the global attributes:
        if root_node.hasAttribute("rootmenuentry"):
            self.RootMenuEntry = root_node.getAttribute("rootmenuentry")
            
        if root_node.hasAttribute("showontoolbar"):
            self.ShowOnToolbar = root_node.getAttribute("showontoolbar").lower() == "true"
            
        if root_node.hasAttribute("shortcutsactive"):
            self.ShortcutsActive = root_node.getAttribute("shortcutsactive").lower() == "true"
            
        # Process the prefs:
        prefs_node = root_node.getElementsByTagName("prefs")
        if prefs_node != None and len(prefs_node) == 1:
            if not self.do_process_prefs( prefs_node[0] ):
                prefs_doc.unlink()
                return False
        else:
            print "There must a single \"prefs\" node inside a \"rwizardsuserprefs\""
            prefs_doc.unlink()
            return False
            
        # Everything seems ok:
        prefs_doc.unlink()
        return True
           
    def do_process_prefs(self,xml_node):
        item_nodes = xml_node.getElementsByTagName("item")
        for item_node in item_nodes:
            # Proces this item:
            item_info = Userprefs_Item()
            if item_node.hasAttribute("rwizard"):
                item_info.Rwizard = item_node.getAttribute("rwizard")
            if item_node.hasAttribute("menu"):
                item_info.Menu = item_node.getAttribute("menu")
            if item_node.hasAttribute("icon"):
                item_info.Icon = item_node.getAttribute("icon")
            if item_node.hasAttribute("toolbar"):
                item_info.Toolbar = item_node.getAttribute("toolbar").lower() == "true"
            if item_node.hasAttribute("shortcut"):
                item_info.Shortcut = item_node.getAttribute("shortcut")
            # Add it to the list:
            self.userprefs = self.userprefs + [item_info]
        return True
        
    # Getters for a particular rwizard, allowing the reconciliation of user defined and default preferences:
    def get_menu(self,name):
        for item_info in self.userprefs:
            if item_info.Rwizard == name:
                if item_info.Menu != None:
                    return item_info.Menu
                else:
                    return self.RootMenuEntry
        return self.RootMenuEntry
        
    def get_icon(self,name):
        for item_info in self.userprefs:
            if item_info.Rwizard == name:
                if item_info.Icon != None:
                    return item_info.Icon
                else:
                    return None
        return None
        
    def get_toolbar(self,name):
        for item_info in self.userprefs:
            if item_info.Rwizard == name:
                if item_info.Toolbar != None:
                    return item_info.Toolbar
                else:
                    return self.ShowOnToolbar
        return self.ShowOnToolbar
        
    def get_shortcut(self,name):
        for item_info in self.userprefs:
            if item_info.Rwizard == name:
                if item_info.Shortcut != None:
                    return item_info.Shortcut
                else:
                    return self.ShortcutsActive
        return self.ShortcutsActive
        
    # Debug printing:
    def print_debug(self):
        print "RWizardEngine: " + " " + str(self.RootMenuEntry) + " " + str(self.ShowOnToolbar) + " " + str(self.ShortcutsActive)
        for item_info in self.userprefs:
            item_info.print_debug()
        for wizard in self.wizards:
            wizard.print_debug()


########################################################################
#                   The Panel with the R file structure
########################################################################

# This class displays the panel tab:
class RStructurePanel:
    def __init__(self,rctrlwindowhelper):
        # Init:
        self._rctrlwindowhelper = rctrlwindowhelper
        self._window = rctrlwindowhelper._window
        self._plugin = rctrlwindowhelper._plugin
        
        # Get the side panel :
        self.side_panel = self._window.get_side_panel()
        
        # The support widget is a vbox:
        self.R_struct_base_vbox = gtk.VBox()
        self.R_struct_base_vbox.show()
        item_icon = gtk.Image()
        pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self._plugin.get_data_dir()+"/R_structure.png" , 16, 16)
        item_icon.set_from_pixbuf(pixbuf)
        item_icon.show()
        self.side_panel.add_item( self.R_struct_base_vbox, _("R structure"), item_icon )
        
        # Which contains an info line and a clickable (read-only) list
        self.force_refresh = gtk.Button(stock="gtk-refresh")
        self.scrolled_window = gtk.ScrolledWindow()
        self.buttons_hbox = gtk.HBox()
        self.buttons_hbox.show()
        # Enable/disable it:
        self.enable_info = gtk.CheckButton(_("Enable?"),False)
        self.enable_info.set_tooltip_text(_("Enable or disable the info concerning the structure of the R file..."))
        self.enable_info.show()
        self.enable_info.connect( "toggled", self.on_enable_info_toggled )
        self.buttons_hbox.pack_start(self.enable_info,False)
        self.enable_info.set_active(self._plugin.prefs['R_structure_enabled'])
            
        # Force refresh:
        self.force_refresh.set_tooltip_text(_("Force refresh of info concerning the structure of the R file..."))
        self.force_refresh.show()
        self.force_refresh.connect( "clicked", self.on_force_refresh )
        self.force_refresh.set_sensitive(self._plugin.prefs['R_structure_enabled'])
        self.buttons_hbox.pack_end(self.force_refresh,False)
        
        self.R_struct_base_vbox.pack_start(self.buttons_hbox,False)

        # The scrollable holder:
        self.scrolled_window.set_shadow_type(gtk.SHADOW_ETCHED_IN)
        self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.scrolled_window.show()
        self.scrolled_window.set_sensitive(self._plugin.prefs['R_structure_enabled'])
        
        # The possible types and associated icons:
        function_definition_icon = gtk.gdk.pixbuf_new_from_file_at_size(self._plugin.get_data_dir()+"/function_definition.png" , 16, 16)
        landmark_definition_icon = gtk.gdk.pixbuf_new_from_file_at_size(self._plugin.get_data_dir()+"/landmark_definition.png" , 16, 16)
        dataframe_defintion_icon = gtk.gdk.pixbuf_new_from_file_at_size(self._plugin.get_data_dir()+"/dataframe_definition.png" , 16, 16)
        self.info_types = {
            'function'   : function_definition_icon,
            'landmark'   : landmark_definition_icon,
            'data.frame' : dataframe_defintion_icon
        }

        # The treeview holding the actual info (line no, icon_type, actual info):
        #self.info_liststore = gtk.ListStore(gobject.TYPE_INT,gtk.gdk.Pixbuf,gobject.TYPE_STRING,gobject.TYPE_STRING)
        self.info_liststore = gtk.ListStore(str,gtk.gdk.Pixbuf,str,str)
        #self.info_liststore.append(["1",self.info_types['function'],"idem","tooltip1"])
        #self.info_liststore.append(["2",self.info_types['landmark'],"x <- 1","tooltip2"])
        
        self.info_treeview  = gtk.TreeView(self.info_liststore)
        
        # The columns:
        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Line", rendererText, text=0)
        column.set_resizable(True)
        #column.set_sort_column_id(0)    
        self.info_treeview.append_column(column)

        rendererPixbuf = gtk.CellRendererPixbuf()
        column = gtk.TreeViewColumn("Type", rendererPixbuf, pixbuf=1)
        #column.set_min_width(25)
        column.set_resizable(True)
        #column.set_sort_column_id(0)    
        self.info_treeview.append_column(column)

        rendererText = gtk.CellRendererText()
        column = gtk.TreeViewColumn("Info", rendererText, text=2)
        column.set_resizable(True)
        #column.set_sort_column_id(0)    
        self.info_treeview.append_column(column)

        self.info_treeview.set_tooltip_column(3)
        self.info_treeview.set_headers_visible(True)
        self.info_treeview.set_headers_clickable(False)
        self.info_treeview.set_reorderable(False)
        self.info_treeview.set_enable_search(True)
        self.info_treeview.set_search_column(2)

        self.info_treeview.show()
        self.scrolled_window.add(self.info_treeview)
        self.R_struct_base_vbox.pack_start(self.scrolled_window,True)
        
        self.info_treeview.connect("row-activated", self.on_inforow_activated)
        
        # The regular expression matcher:
        self.create_pattern_matcher()
        #self._pattern_matcher = re.compile( r"[ \t]*"+landmark_comment_header + # a landmark comment
        #                                    r"|" + # or
        #                                    r"function\(" # a function defintion
        #                                  )
                                          
    def create_pattern_matcher(self):
        # Create the appriate pattern matcher given the options:
        pattern_definition = r""
        if self._plugin.prefs['R_structure_landmarks']:
            pattern_definition += r"[ \t]*"+landmark_comment_header
        if self._plugin.prefs['R_structure_functions']:
            pattern_definition += (r"|" if len(pattern_definition) > 0 else r"") + r"function\("
        if self._plugin.prefs['R_structure_dataframes']:
            pattern_definition += (r"|" if len(pattern_definition) > 0 else r"") + r"data\.frame\("
        
        self._pattern_matcher = re.compile(pattern_definition)
        
    def on_enable_info_toggled(self,checkbutton):
        # The enable R info checkbutton has been toggled:
        self._plugin.prefs['R_structure_enabled'] = checkbutton.get_active()
        self._plugin.save_prefs()
        self.force_refresh.set_sensitive(self._plugin.prefs['R_structure_enabled'])
        self.scrolled_window.set_sensitive(self._plugin.prefs['R_structure_enabled'])
        
        # Frce a refresh:
        if self._plugin.prefs['R_structure_enabled']:
            doc = self._window.get_active_document()
            if not doc:
                return
            self.parse_R_document_for_landmarks(doc)
        
    def on_force_refresh(self,button):
        # Force a refresh of the structure:
        doc = self._window.get_active_document()
        if not doc:
            return
        self.parse_R_document_for_landmarks(doc)
        
    def on_inforow_activated(self,widget, row, col):
        # The row has been activated by the user:
        model = widget.get_model()
        doc = self._window.get_active_document()
        if not doc:
            return
        view = self._window.get_active_view()
        if not view:
            return
            
        try:
            line_no = int(model[row][0])
        except:
            error_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, 'The line number "' + model[row][0] + '" is illegal!' )
            error_dialog.run()
            error_dialog.destroy()
            return
        if line_no < 0 or line_no > doc.get_line_count():
            error_dialog = gtk.MessageDialog( None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "The line number must be a positive integer smaller than the number of lines in the document!" )
            error_dialog.run()
            error_dialog.destroy()
            return
            
        goal_line = doc.get_iter_at_line(line_no-1)
        doc.place_cursor(goal_line)
        #view.scroll_mark_onscreen(doc.get_insert())
        view.scroll_to_mark(doc.get_insert(),0.25,True)
        view.grab_focus()
        
    def parse_landmark_text(self,text,type):
        # Parse the landmark text (get rid of the trailing standardized header of a comment landmark:
        if type != "function(" and type != "data.frame(":
            # Landmark comment:
            return text[len(landmark_comment_header):].strip()
        else:
            return text

    def parse_R_document_for_landmarks(self,doc):
        if not self._plugin.prefs['R_structure_enabled']:
            # Widget disabled:
            return
            
        # Parse the R document held by doc for landmarks or function defintions and update the listview accordingly
        # Save the current selection (if any):
        self.selection = self.info_treeview.get_selection().get_selected_rows()[1]
        
        self.info_liststore.clear() # clear the listview of the old items
        # Get the whole text:
        whole_text = doc.get_text(doc.get_start_iter(),doc.get_end_iter())
        
        # Search it for function defintions and landmark comments:
        #start_time = time.clock() # timing for debug
        matches = self._pattern_matcher.finditer(whole_text)
        for match in matches:
            # Get the corresponding position in the document for the match:
            line_no = doc.get_iter_at_offset(match.start()).get_line()
            start = doc.get_iter_at_line(line_no)
            end = start.copy()
            end.forward_line()
            line_text = doc.get_text(start,end).strip()
            # Add this info to the list:
            self.info_liststore.append([line_no+1,(self.info_types['function'] if match.group() == "function(" else (self.info_types['data.frame'] if match.group() == "data.frame(" else self.info_types['landmark'])),self.parse_landmark_text(line_text,match.group()),xml.sax.saxutils.escape(line_text)])
        #print (time.clock() - start_time)*1000
        
        # Restore the old selection, if possible:
        if len(self.selection) > 0:
            # There was a selection:
            self.info_treeview.set_cursor_on_cell(self.selection[0])
        else:
            # There was no selection: select the first item (if any):
            self.info_treeview.set_cursor_on_cell((0,))
        return


    
